From: Greg Kroah-Hartman Date: Thu, 25 Jun 2026 11:43:56 +0000 (+0100) Subject: 6.6-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df00162d1db4202941b062b273fb5f72b1a9b680;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch ftrace-do-not-over-allocate-ftrace-memory.patch ftrace-have-ftrace-pages-output-reflect-freed-pages.patch ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch ftrace-update-the-mcount_loc-check-of-skipped-entries.patch scripts-sorttable-add-helper-functions-for-elf_ehdr.patch scripts-sorttable-add-helper-functions-for-elf_shdr.patch scripts-sorttable-add-helper-functions-for-elf_sym.patch scripts-sorttable-allow-matches-to-functions-before-function-entry.patch scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch scripts-sorttable-convert-elf_ehdr-to-union.patch scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch scripts-sorttable-make-compare_extable-into-two-functions.patch scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch scripts-sorttable-remove-unneeded-elf_rel.patch scripts-sorttable-remove-unused-macro-defines.patch scripts-sorttable-remove-unused-write-functions.patch scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch scripts-sorttable-use-uint64_t-for-mcount-sorting.patch scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch --- diff --git a/queue-6.6/arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch b/queue-6.6/arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch new file mode 100644 index 0000000000..e4076d9285 --- /dev/null +++ b/queue-6.6/arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch @@ -0,0 +1,363 @@ +From stable+bounces-267252-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:42 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:54 -0400 +Subject: arm64: scripts/sorttable: Implement sorting mcount_loc at boot for arm64 +To: +Cc: , , , , , +Message-ID: <34c0fa5cbf88c107dab3e707f39fdddb29153cb3.1781814134.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit b3d09d06e052e1d754645acea4e4d1e96f81c934 ] + +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: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Heiko Carstens +Cc: Will Deacon +Cc: Vasily Gorbik +Cc: Alexander Gordeev +Link: https://lore.kernel.org/20250218200022.373319428@goodmis.org +Acked-by: Catalin Marinas +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/Kconfig | 1 + scripts/sorttable.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 183 insertions(+), 3 deletions(-) + +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -202,6 +202,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_FAST_GUP + select HAVE_FTRACE_MCOUNT_RECORD +--- 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 * + 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 *star + 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 fna + 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 fna + } + + 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 fna + .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 fna + .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; diff --git a/queue-6.6/ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch b/queue-6.6/ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch new file mode 100644 index 0000000000..99330fde4a --- /dev/null +++ b/queue-6.6/ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch @@ -0,0 +1,81 @@ +From stable+bounces-267260-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:53 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:39:02 -0400 +Subject: ftrace: Check against is_kernel_text() instead of kaslr_offset() +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit da0f622b344be769ed61e7c1caf95cd0cdb47964 ] + +As kaslr_offset() is architecture dependent and also may not be defined by +all architectures, when zeroing out unused weak functions, do not check +against kaslr_offset(), but instead check if the address is within the +kernel text sections. If KASLR added a shift to the zeroed out function, +it would still not be located in the kernel text. This is a more robust +way to test if the text is valid or not. + +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Masahiro Yamada +Cc: Catalin Marinas +Cc: Will Deacon +Cc: "Arnd Bergmann" +Link: https://lore.kernel.org/20250225182054.471759017@goodmis.org +Fixes: ef378c3b8233 ("scripts/sorttable: Zero out weak functions in mcount_loc table") +Reported-by: Nathan Chancellor +Reported-by: Mark Brown +Tested-by: Nathan Chancellor +Closes: https://lore.kernel.org/all/20250224180805.GA1536711@ax162/ +Closes: https://lore.kernel.org/all/5225b07b-a9b2-4558-9d5f-aa60b19f6317@sirena.org.uk/ +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -6528,7 +6528,6 @@ static int ftrace_process_locs(struct mo + unsigned long count; + unsigned long *p; + unsigned long addr; +- unsigned long kaslr; + unsigned long flags = 0; /* Shut up gcc */ + unsigned long pages; + int ret = -ENOMEM; +@@ -6578,9 +6577,6 @@ static int ftrace_process_locs(struct mo + 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) { +@@ -6594,7 +6590,18 @@ static int ftrace_process_locs(struct mo + * object files to satisfy alignments. + * Skip any NULL pointers. + */ +- if (!addr || addr == kaslr) { ++ if (!addr) { ++ skipped++; ++ continue; ++ } ++ ++ /* ++ * If this is core kernel, make sure the address is in core ++ * or inittext, as weak functions get zeroed and KASLR can ++ * move them to something other than zero. It just will not ++ * move it to an area where kernel text is. ++ */ ++ if (!mod && !(is_kernel_text(addr) || is_kernel_inittext(addr))) { + skipped++; + continue; + } diff --git a/queue-6.6/ftrace-do-not-over-allocate-ftrace-memory.patch b/queue-6.6/ftrace-do-not-over-allocate-ftrace-memory.patch new file mode 100644 index 0000000000..3a02b33ac4 --- /dev/null +++ b/queue-6.6/ftrace-do-not-over-allocate-ftrace-memory.patch @@ -0,0 +1,163 @@ +From stable+bounces-267258-greg=kroah.com@vger.kernel.org Thu Jun 18 21:40:06 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:39:00 -0400 +Subject: ftrace: Do not over-allocate ftrace memory +To: +Cc: , , , , , +Message-ID: <8903a4475ee0044f3c5c7236db3abdd0171e3897.1781814154.git.andrey.grodzovsky@crowdstrike.com> + +From: Guenter Roeck + +[ Upstream commit be55257fab181b93af38f8c4b1b3cb453a78d742 ] + +The pg_remaining calculation in ftrace_process_locs() assumes that +ENTRIES_PER_PAGE multiplied by 2^order equals the actual capacity of the +allocated page group. However, ENTRIES_PER_PAGE is PAGE_SIZE / ENTRY_SIZE +(integer division). When PAGE_SIZE is not a multiple of ENTRY_SIZE (e.g. +4096 / 24 = 170 with remainder 16), high-order allocations (like 256 pages) +have significantly more capacity than 256 * 170. This leads to pg_remaining +being underestimated, which in turn makes skip (derived from skipped - +pg_remaining) larger than expected, causing the WARN(skip != remaining) +to trigger. + +Extra allocated pages for ftrace: 2 with 654 skipped +WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:7295 ftrace_process_locs+0x5bf/0x5e0 + +A similar problem in ftrace_allocate_records() can result in allocating +too many pages. This can trigger the second warning in +ftrace_process_locs(). + +Extra allocated pages for ftrace +WARNING: CPU: 0 PID: 0 at kernel/trace/ftrace.c:7276 ftrace_process_locs+0x548/0x580 + +Use the actual capacity of a page group to determine the number of pages +to allocate. Have ftrace_allocate_pages() return the number of allocated +pages to avoid having to calculate it. Use the actual page group capacity +when validating the number of unused pages due to skipped entries. +Drop the definition of ENTRIES_PER_PAGE since it is no longer used. + +Cc: stable@vger.kernel.org +Fixes: 4a3efc6baff93 ("ftrace: Update the mcount_loc check of skipped entries") +Link: https://patch.msgid.link/20260113152243.3557219-1-linux@roeck-us.net +Signed-off-by: Guenter Roeck +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 29 +++++++++++++++-------------- + 1 file changed, 15 insertions(+), 14 deletions(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -1117,7 +1117,6 @@ struct ftrace_page { + }; + + #define ENTRY_SIZE sizeof(struct dyn_ftrace) +-#define ENTRIES_PER_PAGE (PAGE_SIZE / ENTRY_SIZE) + + static struct ftrace_page *ftrace_pages_start; + static struct ftrace_page *ftrace_pages; +@@ -3245,7 +3244,8 @@ static int ftrace_update_code(struct mod + return 0; + } + +-static int ftrace_allocate_records(struct ftrace_page *pg, int count) ++static int ftrace_allocate_records(struct ftrace_page *pg, int count, ++ unsigned long *num_pages) + { + int order; + int pages; +@@ -3255,7 +3255,7 @@ static int ftrace_allocate_records(struc + return -EINVAL; + + /* We want to fill as much as possible, with no empty pages */ +- pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE); ++ pages = DIV_ROUND_UP(count * ENTRY_SIZE, PAGE_SIZE); + order = fls(pages) - 1; + + again: +@@ -3270,6 +3270,7 @@ static int ftrace_allocate_records(struc + } + + ftrace_number_of_pages += 1 << order; ++ *num_pages += 1 << order; + ftrace_number_of_groups++; + + cnt = (PAGE_SIZE << order) / ENTRY_SIZE; +@@ -3298,12 +3299,14 @@ static void ftrace_free_pages(struct ftr + } + + static struct ftrace_page * +-ftrace_allocate_pages(unsigned long num_to_init) ++ftrace_allocate_pages(unsigned long num_to_init, unsigned long *num_pages) + { + struct ftrace_page *start_pg; + struct ftrace_page *pg; + int cnt; + ++ *num_pages = 0; ++ + if (!num_to_init) + return NULL; + +@@ -3317,7 +3320,7 @@ ftrace_allocate_pages(unsigned long num_ + * waste as little space as possible. + */ + for (;;) { +- cnt = ftrace_allocate_records(pg, num_to_init); ++ cnt = ftrace_allocate_records(pg, num_to_init, num_pages); + if (cnt < 0) + goto free_pages; + +@@ -6535,8 +6538,6 @@ static int ftrace_process_locs(struct mo + 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 +@@ -6549,7 +6550,7 @@ static int ftrace_process_locs(struct mo + test_is_sorted(start, count); + } + +- start_pg = ftrace_allocate_pages(count); ++ start_pg = ftrace_allocate_pages(count, &pages); + if (!start_pg) + return -ENOMEM; + +@@ -6636,27 +6637,27 @@ static int ftrace_process_locs(struct mo + /* We should have used all pages unless we skipped some */ + if (pg_unuse) { + unsigned long pg_remaining, remaining = 0; +- unsigned long skip; ++ long skip; + + /* Count the number of entries unused and compare it to skipped. */ +- pg_remaining = (ENTRIES_PER_PAGE << pg->order) - pg->index; ++ pg_remaining = (PAGE_SIZE << pg->order) / ENTRY_SIZE - pg->index; + + if (!WARN(skipped < pg_remaining, "Extra allocated pages for ftrace")) { + + skip = skipped - pg_remaining; + +- for (pg = pg_unuse; pg; pg = pg->next) ++ for (pg = pg_unuse; pg && skip > 0; pg = pg->next) { + remaining += 1 << pg->order; ++ skip -= (PAGE_SIZE << pg->order) / ENTRY_SIZE; ++ } + + pages -= remaining; + +- 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", ++ WARN(pg || skip > 0, "Extra allocated pages for ftrace: %lu with %lu skipped", + remaining, skipped); + } + /* Need to synchronize with ftrace_location_range() */ diff --git a/queue-6.6/ftrace-have-ftrace-pages-output-reflect-freed-pages.patch b/queue-6.6/ftrace-have-ftrace-pages-output-reflect-freed-pages.patch new file mode 100644 index 0000000000..6aba7446bb --- /dev/null +++ b/queue-6.6/ftrace-have-ftrace-pages-output-reflect-freed-pages.patch @@ -0,0 +1,112 @@ +From stable+bounces-267257-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:58 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:59 -0400 +Subject: ftrace: Have ftrace pages output reflect freed pages +To: +Cc: , , , , , +Message-ID: <05b8a27b8714dc88569d22f4b5faf538b1159b14.1781814151.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 264143c4e54412095f4b615e65bf736fc3c60af0 ] + +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. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Heiko Carstens +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Vasily Gorbik +Cc: Alexander Gordeev +Link: https://lore.kernel.org/20250218200023.221100846@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -6527,6 +6527,7 @@ static int ftrace_process_locs(struct mo + unsigned long addr; + unsigned long kaslr; + unsigned long flags = 0; /* Shut up gcc */ ++ unsigned long pages; + int ret = -ENOMEM; + + count = end - start; +@@ -6534,6 +6535,8 @@ static int ftrace_process_locs(struct mo + 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 +@@ -6645,6 +6648,8 @@ static int ftrace_process_locs(struct mo + for (pg = pg_unuse; pg; pg = pg->next) + remaining += 1 << pg->order; + ++ pages -= remaining; ++ + skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE); + + /* +@@ -6658,6 +6663,13 @@ static int ftrace_process_locs(struct mo + 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; + } + +@@ -7315,9 +7327,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); diff --git a/queue-6.6/ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch b/queue-6.6/ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch new file mode 100644 index 0000000000..1fa45f0761 --- /dev/null +++ b/queue-6.6/ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch @@ -0,0 +1,62 @@ +From stable+bounces-267259-greg=kroah.com@vger.kernel.org Thu Jun 18 21:40:06 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:39:01 -0400 +Subject: ftrace: Test mcount_loc addr before calling ftrace_call_addr() +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit 6eeca746fa5f1dd03c6ee05cb03f5eb1ddda1c81 ] + +The addresses in the mcount_loc can be zeroed and then moved by KASLR +making them invalid addresses. ftrace_call_addr() for ARM 64 expects a +valid address to kernel text. If the addr read from the mcount_loc section +is invalid, it must not call ftrace_call_addr(). Move the addr check +before calling ftrace_call_addr() in ftrace_process_locs(). + +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Masahiro Yamada +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Mark Brown +Link: https://lore.kernel.org/20250225182054.290128736@goodmis.org +Fixes: ef378c3b8233 ("scripts/sorttable: Zero out weak functions in mcount_loc table") +Reported-by: Nathan Chancellor +Reported-by: "Arnd Bergmann" +Tested-by: Nathan Chancellor +Closes: https://lore.kernel.org/all/20250225025631.GA271248@ax162/ +Closes: https://lore.kernel.org/all/91523154-072b-437b-bbdc-0b70e9783fd0@app.fastmail.com/ +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -6585,7 +6585,9 @@ static int ftrace_process_locs(struct mo + pg = start_pg; + while (p < end) { + unsigned long end_offset; +- addr = ftrace_call_adjust(*p++); ++ ++ addr = *p++; ++ + /* + * Some architecture linkers will pad between + * the different mcount_loc sections of different +@@ -6597,6 +6599,8 @@ static int ftrace_process_locs(struct mo + continue; + } + ++ addr = ftrace_call_adjust(addr); ++ + end_offset = (pg->index+1) * sizeof(pg->records[0]); + if (end_offset > PAGE_SIZE << pg->order) { + /* We should have allocated enough */ diff --git a/queue-6.6/ftrace-update-the-mcount_loc-check-of-skipped-entries.patch b/queue-6.6/ftrace-update-the-mcount_loc-check-of-skipped-entries.patch new file mode 100644 index 0000000000..0976ca41ef --- /dev/null +++ b/queue-6.6/ftrace-update-the-mcount_loc-check-of-skipped-entries.patch @@ -0,0 +1,75 @@ +From stable+bounces-267256-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:47 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:58 -0400 +Subject: ftrace: Update the mcount_loc check of skipped entries +To: +Cc: , , , , , +Message-ID: <5c2b0521f89d30eca030b4f67c0483955d7af6a0.1781814148.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 4a3efc6baff931da9a85c6d2e42c87bd9a827399 ] + +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. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Heiko Carstens +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Vasily Gorbik +Cc: Alexander Gordeev +Link: https://lore.kernel.org/20250218200023.055162048@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -6632,7 +6632,28 @@ static int ftrace_process_locs(struct mo + + /* We should have used all pages unless we skipped some */ + if (pg_unuse) { +- WARN_ON(!skipped); ++ unsigned long pg_remaining, remaining = 0; ++ 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); diff --git a/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_ehdr.patch b/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_ehdr.patch new file mode 100644 index 0000000000..3e6d73d175 --- /dev/null +++ b/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_ehdr.patch @@ -0,0 +1,135 @@ +From stable+bounces-267245-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:30 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:47 -0400 +Subject: scripts/sorttable: Add helper functions for Elf_Ehdr +To: +Cc: , , , , , +Message-ID: <629ff1458625033b72bdb9e4e976c91da8b23f92.1781814113.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 1dfb59a228dde59ad7d99b2fa2104e90004995c7 ] + +In order to remove the double #include of sorttable.h for 64 and 32 bit +to create duplicate functions, add helper functions for Elf_Ehdr. This +will create a function pointer for each helper that will get assigned to +the appropriate function to handle either the 64bit or 32bit version. + +This also moves the _r()/r() wrappers for the Elf_Ehdr references that +handle endian and size differences between the different architectures, +into the helper function and out of the open code which is more error +prone. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162345.736369526@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 25 +++++++++++++++++++++++++ + scripts/sorttable.h | 20 ++++++++++++++++---- + 2 files changed, 41 insertions(+), 4 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -85,6 +85,31 @@ static uint64_t (*r8)(const uint64_t *); + static void (*w)(uint32_t, uint32_t *); + typedef void (*table_sort_t)(char *, int); + ++static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) ++{ ++ return r8(&ehdr->e64.e_shoff); ++} ++ ++static uint64_t ehdr32_shoff(Elf_Ehdr *ehdr) ++{ ++ return r(&ehdr->e32.e_shoff); ++} ++ ++#define EHDR_HALF(fn_name) \ ++static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \ ++{ \ ++ return r2(&ehdr->e64.e_##fn_name); \ ++} \ ++ \ ++static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \ ++{ \ ++ return r2(&ehdr->e32.e_##fn_name); \ ++} ++ ++EHDR_HALF(shentsize) ++EHDR_HALF(shstrndx) ++EHDR_HALF(shnum) ++ + /* + * Get the whole file as a programming convenience in order to avoid + * malloc+lseek+read+free of many pieces. If successful, then mmap +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -27,6 +27,10 @@ + #undef uint_t + #undef _r + #undef etype ++#undef ehdr_shoff ++#undef ehdr_shentsize ++#undef ehdr_shstrndx ++#undef ehdr_shnum + + #ifdef SORTTABLE_64 + # define extable_ent_size 16 +@@ -39,6 +43,10 @@ + # define uint_t uint64_t + # define _r r8 + # define etype e64 ++# define ehdr_shoff ehdr64_shoff ++# define ehdr_shentsize ehdr64_shentsize ++# define ehdr_shstrndx ehdr64_shstrndx ++# define ehdr_shnum ehdr64_shnum + #else + # define extable_ent_size 8 + # define compare_extable compare_extable_32 +@@ -50,6 +58,10 @@ + # define uint_t uint32_t + # define _r r + # define etype e32 ++# define ehdr_shoff ehdr32_shoff ++# define ehdr_shentsize ehdr32_shentsize ++# define ehdr_shstrndx ehdr32_shstrndx ++# define ehdr_shnum ehdr32_shnum + #endif + + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +@@ -250,16 +262,16 @@ static int do_sort(Elf_Ehdr *ehdr, + unsigned int orc_num_entries = 0; + #endif + +- shdr_start = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff)); +- shentsize = r2(&ehdr->etype.e_shentsize); ++ shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); ++ shentsize = ehdr_shentsize(ehdr); + +- shstrndx = r2(&ehdr->etype.e_shstrndx); ++ shstrndx = ehdr_shstrndx(ehdr); + if (shstrndx == SHN_XINDEX) + shstrndx = r(&shdr_start->etype.sh_link); + string_sec = get_index(shdr_start, shentsize, shstrndx); + secstrings = (const char *)ehdr + _r(&string_sec->etype.sh_offset); + +- shnum = r2(&ehdr->etype.e_shnum); ++ shnum = ehdr_shnum(ehdr); + if (shnum == SHN_UNDEF) + shnum = _r(&shdr_start->etype.sh_size); + diff --git a/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_shdr.patch b/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_shdr.patch new file mode 100644 index 0000000000..32b2585099 --- /dev/null +++ b/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_shdr.patch @@ -0,0 +1,249 @@ +From stable+bounces-267246-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:30 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:48 -0400 +Subject: scripts/sorttable: Add helper functions for Elf_Shdr +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit 67afb7f504400e5b4e5ff895459fbb3eb63d4450 ] + +In order to remove the double #include of sorttable.h for 64 and 32 bit +to create duplicate functions, add helper functions for Elf_Shdr. This +will create a function pointer for each helper that will get assigned to +the appropriate function to handle either the 64bit or 32bit version. + +This also moves the _r()/r() wrappers for the Elf_Shdr references that +handle endian and size differences between the different architectures, +into the helper function and out of the open code which is more error +prone. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162345.940924221@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 42 +++++++++++++++++++++++++++++++++ + scripts/sorttable.h | 66 +++++++++++++++++++++++++++++++++------------------- + 2 files changed, 85 insertions(+), 23 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -110,6 +110,48 @@ EHDR_HALF(shentsize) + EHDR_HALF(shstrndx) + EHDR_HALF(shnum) + ++#define SHDR_WORD(fn_name) \ ++static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return r(&shdr->e64.sh_##fn_name); \ ++} \ ++ \ ++static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return r(&shdr->e32.sh_##fn_name); \ ++} ++ ++#define SHDR_ADDR(fn_name) \ ++static uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return r8(&shdr->e64.sh_##fn_name); \ ++} \ ++ \ ++static uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return r(&shdr->e32.sh_##fn_name); \ ++} ++ ++#define SHDR_WORD(fn_name) \ ++static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return r(&shdr->e64.sh_##fn_name); \ ++} \ ++ \ ++static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return r(&shdr->e32.sh_##fn_name); \ ++} ++ ++SHDR_ADDR(addr) ++SHDR_ADDR(offset) ++SHDR_ADDR(size) ++SHDR_ADDR(entsize) ++ ++SHDR_WORD(link) ++SHDR_WORD(name) ++SHDR_WORD(type) ++ + /* + * Get the whole file as a programming convenience in order to avoid + * malloc+lseek+read+free of many pieces. If successful, then mmap +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -31,6 +31,13 @@ + #undef ehdr_shentsize + #undef ehdr_shstrndx + #undef ehdr_shnum ++#undef shdr_addr ++#undef shdr_offset ++#undef shdr_link ++#undef shdr_size ++#undef shdr_name ++#undef shdr_type ++#undef shdr_entsize + + #ifdef SORTTABLE_64 + # define extable_ent_size 16 +@@ -47,6 +54,13 @@ + # define ehdr_shentsize ehdr64_shentsize + # define ehdr_shstrndx ehdr64_shstrndx + # define ehdr_shnum ehdr64_shnum ++# define shdr_addr shdr64_addr ++# define shdr_offset shdr64_offset ++# define shdr_link shdr64_link ++# define shdr_size shdr64_size ++# define shdr_name shdr64_name ++# define shdr_type shdr64_type ++# define shdr_entsize shdr64_entsize + #else + # define extable_ent_size 8 + # define compare_extable compare_extable_32 +@@ -62,6 +76,13 @@ + # define ehdr_shentsize ehdr32_shentsize + # define ehdr_shstrndx ehdr32_shstrndx + # define ehdr_shnum ehdr32_shnum ++# define shdr_addr shdr32_addr ++# define shdr_offset shdr32_offset ++# define shdr_link shdr32_link ++# define shdr_size shdr32_size ++# define shdr_name shdr32_name ++# define shdr_type shdr32_type ++# define shdr_entsize shdr32_entsize + #endif + + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +@@ -177,8 +198,8 @@ struct elf_mcount_loc { + static void *sort_mcount_loc(void *arg) + { + struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg; +- uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->etype.sh_addr) +- + _r(&(emloc->init_data_sec)->etype.sh_offset); ++ uint_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec) ++ + shdr_offset(emloc->init_data_sec); + uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; + unsigned char *start_loc = (void *)emloc->ehdr + offset; + +@@ -267,18 +288,18 @@ static int do_sort(Elf_Ehdr *ehdr, + + shstrndx = ehdr_shstrndx(ehdr); + if (shstrndx == SHN_XINDEX) +- shstrndx = r(&shdr_start->etype.sh_link); ++ shstrndx = shdr_link(shdr_start); + string_sec = get_index(shdr_start, shentsize, shstrndx); +- secstrings = (const char *)ehdr + _r(&string_sec->etype.sh_offset); ++ secstrings = (const char *)ehdr + shdr_offset(string_sec); + + shnum = ehdr_shnum(ehdr); + if (shnum == SHN_UNDEF) +- shnum = _r(&shdr_start->etype.sh_size); ++ shnum = shdr_size(shdr_start); + + for (i = 0; i < shnum; i++) { + Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); + +- idx = r(&shdr->etype.sh_name); ++ idx = shdr_name(shdr); + if (!strcmp(secstrings + idx, "__ex_table")) + extab_sec = shdr; + if (!strcmp(secstrings + idx, ".symtab")) +@@ -286,9 +307,9 @@ static int do_sort(Elf_Ehdr *ehdr, + if (!strcmp(secstrings + idx, ".strtab")) + strtab_sec = shdr; + +- if (r(&shdr->etype.sh_type) == SHT_SYMTAB_SHNDX) ++ if (shdr_type(shdr) == SHT_SYMTAB_SHNDX) + symtab_shndx = (Elf32_Word *)((const char *)ehdr + +- _r(&shdr->etype.sh_offset)); ++ shdr_offset(shdr)); + + #ifdef MCOUNT_SORT_ENABLED + /* locate the .init.data section in vmlinux */ +@@ -304,14 +325,14 @@ static int do_sort(Elf_Ehdr *ehdr, + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + /* locate the ORC unwind tables */ + if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { +- orc_ip_size = _r(&shdr->etype.sh_size); ++ orc_ip_size = shdr_size(shdr); + g_orc_ip_table = (int *)((void *)ehdr + +- _r(&shdr->etype.sh_offset)); ++ shdr_offset(shdr)); + } + if (!strcmp(secstrings + idx, ".orc_unwind")) { +- orc_size = _r(&shdr->etype.sh_size); ++ orc_size = shdr_size(shdr); + g_orc_table = (struct orc_entry *)((void *)ehdr + +- _r(&shdr->etype.sh_offset)); ++ shdr_offset(shdr)); + } + #endif + } /* for loop */ +@@ -374,23 +395,22 @@ static int do_sort(Elf_Ehdr *ehdr, + goto out; + } + +- extab_image = (void *)ehdr + _r(&extab_sec->etype.sh_offset); +- strtab = (const char *)ehdr + _r(&strtab_sec->etype.sh_offset); +- symtab = (const Elf_Sym *)((const char *)ehdr + +- _r(&symtab_sec->etype.sh_offset)); ++ extab_image = (void *)ehdr + shdr_offset(extab_sec); ++ strtab = (const char *)ehdr + shdr_offset(strtab_sec); ++ symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec)); + + if (custom_sort) { +- custom_sort(extab_image, _r(&extab_sec->etype.sh_size)); ++ custom_sort(extab_image, shdr_size(extab_sec)); + } else { +- int num_entries = _r(&extab_sec->etype.sh_size) / extable_ent_size; ++ int num_entries = shdr_size(extab_sec) / extable_ent_size; + qsort(extab_image, num_entries, + extable_ent_size, compare_extable); + } + + /* find the flag main_extable_sort_needed */ +- sym_start = (void *)ehdr + _r(&symtab_sec->etype.sh_offset); +- sym_end = sym_start + _r(&symtab_sec->etype.sh_size); +- symentsize = _r(&symtab_sec->etype.sh_entsize); ++ sym_start = (void *)ehdr + shdr_offset(symtab_sec); ++ sym_end = sym_start + shdr_size(symtab_sec); ++ symentsize = shdr_entsize(symtab_sec); + + for (sym = sym_start; (void *)sym + symentsize < sym_end; + sym = (void *)sym + symentsize) { +@@ -415,9 +435,9 @@ static int do_sort(Elf_Ehdr *ehdr, + symtab_shndx); + sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index); + sort_needed_loc = (void *)ehdr + +- _r(&sort_needed_sec->etype.sh_offset) + ++ shdr_offset(sort_needed_sec) + + _r(&sort_needed_sym->etype.st_value) - +- _r(&sort_needed_sec->etype.sh_addr); ++ shdr_addr(sort_needed_sec); + + /* extable has been sorted, clear the flag */ + w(0, sort_needed_loc); diff --git a/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_sym.patch b/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_sym.patch new file mode 100644 index 0000000000..eab045995a --- /dev/null +++ b/queue-6.6/scripts-sorttable-add-helper-functions-for-elf_sym.patch @@ -0,0 +1,199 @@ +From stable+bounces-267247-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:35 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:49 -0400 +Subject: scripts/sorttable: Add helper functions for Elf_Sym +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit 17bed33ac12f011f4695059960e1b1d6457229a7 ] + +In order to remove the double #include of sorttable.h for 64 and 32 bit +to create duplicate functions, add helper functions for Elf_Sym. This +will create a function pointer for each helper that will get assigned to +the appropriate function to handle either the 64bit or 32bit version. + +This also removes the last references of etype and _r() macros from the +sorttable.h file as their references are now just defined in the +appropriate architecture version of the helper functions. All read +functions now exist in the helper functions which makes it easier to +maintain, as the helper functions define the necessary architecture sizes. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162346.185740651@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + scripts/sorttable.h | 30 ++++++++++++++++-------------- + 2 files changed, 63 insertions(+), 14 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -152,6 +152,53 @@ SHDR_WORD(link) + SHDR_WORD(name) + SHDR_WORD(type) + ++#define SYM_ADDR(fn_name) \ ++static uint64_t sym64_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return r8(&sym->e64.st_##fn_name); \ ++} \ ++ \ ++static uint64_t sym32_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return r(&sym->e32.st_##fn_name); \ ++} ++ ++#define SYM_WORD(fn_name) \ ++static uint32_t sym64_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return r(&sym->e64.st_##fn_name); \ ++} \ ++ \ ++static uint32_t sym32_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return r(&sym->e32.st_##fn_name); \ ++} ++ ++#define SYM_HALF(fn_name) \ ++static uint16_t sym64_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return r2(&sym->e64.st_##fn_name); \ ++} \ ++ \ ++static uint16_t sym32_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return r2(&sym->e32.st_##fn_name); \ ++} ++ ++static uint8_t sym64_type(Elf_Sym *sym) ++{ ++ return ELF64_ST_TYPE(sym->e64.st_info); ++} ++ ++static uint8_t sym32_type(Elf_Sym *sym) ++{ ++ return ELF32_ST_TYPE(sym->e32.st_info); ++} ++ ++SYM_ADDR(value) ++SYM_WORD(name) ++SYM_HALF(shndx) ++ + /* + * Get the whole file as a programming convenience in order to avoid + * malloc+lseek+read+free of many pieces. If successful, then mmap +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -23,10 +23,7 @@ + #undef sort_mcount_loc + #undef elf_mcount_loc + #undef do_sort +-#undef ELF_ST_TYPE + #undef uint_t +-#undef _r +-#undef etype + #undef ehdr_shoff + #undef ehdr_shentsize + #undef ehdr_shstrndx +@@ -38,6 +35,10 @@ + #undef shdr_name + #undef shdr_type + #undef shdr_entsize ++#undef sym_type ++#undef sym_name ++#undef sym_value ++#undef sym_shndx + + #ifdef SORTTABLE_64 + # define extable_ent_size 16 +@@ -46,10 +47,7 @@ + # define sort_mcount_loc sort_mcount_loc_64 + # define elf_mcount_loc elf_mcount_loc_64 + # define do_sort do_sort_64 +-# define ELF_ST_TYPE ELF64_ST_TYPE + # define uint_t uint64_t +-# define _r r8 +-# define etype e64 + # define ehdr_shoff ehdr64_shoff + # define ehdr_shentsize ehdr64_shentsize + # define ehdr_shstrndx ehdr64_shstrndx +@@ -61,6 +59,10 @@ + # define shdr_name shdr64_name + # define shdr_type shdr64_type + # define shdr_entsize shdr64_entsize ++# define sym_type sym64_type ++# define sym_name sym64_name ++# define sym_value sym64_value ++# define sym_shndx sym64_shndx + #else + # define extable_ent_size 8 + # define compare_extable compare_extable_32 +@@ -68,10 +70,7 @@ + # define sort_mcount_loc sort_mcount_loc_32 + # define elf_mcount_loc elf_mcount_loc_32 + # define do_sort do_sort_32 +-# define ELF_ST_TYPE ELF32_ST_TYPE + # define uint_t uint32_t +-# define _r r +-# define etype e32 + # define ehdr_shoff ehdr32_shoff + # define ehdr_shentsize ehdr32_shentsize + # define ehdr_shstrndx ehdr32_shstrndx +@@ -83,6 +82,10 @@ + # define shdr_name shdr32_name + # define shdr_type shdr32_type + # define shdr_entsize shdr32_entsize ++# define sym_type sym32_type ++# define sym_name sym32_name ++# define sym_value sym32_value ++# define sym_shndx sym32_shndx + #endif + + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +@@ -414,9 +417,9 @@ static int do_sort(Elf_Ehdr *ehdr, + + for (sym = sym_start; (void *)sym + symentsize < sym_end; + sym = (void *)sym + symentsize) { +- if (ELF_ST_TYPE(sym->etype.st_info) != STT_OBJECT) ++ if (sym_type(sym) != STT_OBJECT) + continue; +- if (!strcmp(strtab + r(&sym->etype.st_name), ++ if (!strcmp(strtab + sym_name(sym), + "main_extable_sort_needed")) { + sort_needed_sym = sym; + break; +@@ -430,14 +433,13 @@ static int do_sort(Elf_Ehdr *ehdr, + goto out; + } + +- sort_need_index = get_secindex(r2(&sym->etype.st_shndx), ++ sort_need_index = get_secindex(sym_shndx(sym), + ((void *)sort_needed_sym - (void *)symtab) / symentsize, + symtab_shndx); + sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index); + sort_needed_loc = (void *)ehdr + + shdr_offset(sort_needed_sec) + +- _r(&sort_needed_sym->etype.st_value) - +- shdr_addr(sort_needed_sec); ++ sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec); + + /* extable has been sorted, clear the flag */ + w(0, sort_needed_loc); diff --git a/queue-6.6/scripts-sorttable-allow-matches-to-functions-before-function-entry.patch b/queue-6.6/scripts-sorttable-allow-matches-to-functions-before-function-entry.patch new file mode 100644 index 0000000000..593f5254ea --- /dev/null +++ b/queue-6.6/scripts-sorttable-allow-matches-to-functions-before-function-entry.patch @@ -0,0 +1,69 @@ +From stable+bounces-267262-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:59 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:39:04 -0400 +Subject: scripts/sorttable: Allow matches to functions before function entry +To: +Cc: , , , , , +Message-ID: <34a497333bb2c39b88c4b6e2dbf4ed63f28e846f.1781814165.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit dc208c69c033d3caba0509da1ae065d2b5ff165f ] + +ARM 64 uses -fpatchable-function-entry=4,2 which adds padding before the +function and the addresses in the mcount_loc point there instead of the +function entry that is returned by nm. In order to find a function from nm +to make sure it's not an unused weak function, the entries in the +mcount_loc section needs to match the entries from nm. Since it can be an +instruction before the entry, add a before_func variable that ARM 64 can +set to 8, and if the mcount_loc entry is within 8 bytes of the nm function +entry, then it will be considered a match. + +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Masahiro Yamada +Cc: Catalin Marinas +Cc: Will Deacon +Cc: "Arnd Bergmann" +Cc: Mark Brown +Link: https://lore.kernel.org/20250225182054.815536219@goodmis.org +Fixes: ef378c3b82338 ("scripts/sorttable: Zero out weak functions in mcount_loc table") +Tested-by: Nathan Chancellor +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -611,13 +611,16 @@ static int add_field(uint64_t addr, uint + return 0; + } + ++/* Used for when mcount/fentry is before the function entry */ ++static int before_func; ++ + /* 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) ++ if (key + before_func < a->addr) + return -1; + return key >= a->addr + a->size; + } +@@ -1253,6 +1256,8 @@ static int do_file(char const *const fna + #ifdef MCOUNT_SORT_ENABLED + sort_reloc = true; + rela_type = 0x403; ++ /* arm64 uses patchable function entry placing before function */ ++ before_func = 8; + #endif + /* fallthrough */ + case EM_386: diff --git a/queue-6.6/scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch b/queue-6.6/scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch new file mode 100644 index 0000000000..7e9b9aa9fb --- /dev/null +++ b/queue-6.6/scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch @@ -0,0 +1,235 @@ +From stable+bounces-267254-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:49 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:56 -0400 +Subject: scripts/sorttable: Always use an array for the mcount_loc sorting +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit 5fb964f5ba53afda0e2b6dbc00b8205461ffe04a ] + +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. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Heiko Carstens +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Vasily Gorbik +Cc: Alexander Gordeev +Link: https://lore.kernel.org/20250218200022.710676551@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 122 ++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 90 insertions(+), 32 deletions(-) + +--- 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 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, + 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, + } + } + } +- 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 */ diff --git a/queue-6.6/scripts-sorttable-convert-elf_ehdr-to-union.patch b/queue-6.6/scripts-sorttable-convert-elf_ehdr-to-union.patch new file mode 100644 index 0000000000..e89740feb1 --- /dev/null +++ b/queue-6.6/scripts-sorttable-convert-elf_ehdr-to-union.patch @@ -0,0 +1,208 @@ +From stable+bounces-267241-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:27 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:44 -0400 +Subject: scripts/sorttable: Convert Elf_Ehdr to union +To: +Cc: , , , , , +Message-ID: <09e64ccae2199a9de0258e3921a1158b928b6ab9.1781814102.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 157fb5b3cfd2cb5950314f926a76e567fc1921c5 ] + +In order to remove the double #include of sorttable.h for 64 and 32 bit +to create duplicate functions for both, replace the Elf_Ehdr macro with a +union that defines both Elf64_Ehdr and Elf32_Ehdr, with field e64 for the +64bit version, and e32 for the 32bit version. + +Then a macro etype can be used instead to get to the proper value. + +This will eventually be replaced with just single functions that can +handle both 32bit and 64bit ELF parsing. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162345.148224465@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 36 ++++++++++++++++++++---------------- + scripts/sorttable.h | 12 ++++++------ + 2 files changed, 26 insertions(+), 22 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -64,6 +64,11 @@ + #define EM_LOONGARCH 258 + #endif + ++typedef union { ++ Elf32_Ehdr e32; ++ Elf64_Ehdr e64; ++} Elf_Ehdr; ++ + static uint32_t (*r)(const uint32_t *); + static uint16_t (*r2)(const uint16_t *); + static uint64_t (*r8)(const uint64_t *); +@@ -266,10 +271,10 @@ static void sort_relative_table_with_dat + static int do_file(char const *const fname, void *addr) + { + int rc = -1; +- Elf32_Ehdr *ehdr = addr; ++ Elf_Ehdr *ehdr = addr; + table_sort_t custom_sort = NULL; + +- switch (ehdr->e_ident[EI_DATA]) { ++ switch (ehdr->e32.e_ident[EI_DATA]) { + case ELFDATA2LSB: + r = rle; + r2 = r2le; +@@ -284,18 +289,18 @@ static int do_file(char const *const fna + break; + default: + fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", +- ehdr->e_ident[EI_DATA], fname); ++ ehdr->e32.e_ident[EI_DATA], fname); + return -1; + } + +- if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 || +- (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN) || +- ehdr->e_ident[EI_VERSION] != EV_CURRENT) { ++ if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) != 0 || ++ (r2(&ehdr->e32.e_type) != ET_EXEC && r2(&ehdr->e32.e_type) != ET_DYN) || ++ ehdr->e32.e_ident[EI_VERSION] != EV_CURRENT) { + fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname); + return -1; + } + +- switch (r2(&ehdr->e_machine)) { ++ switch (r2(&ehdr->e32.e_machine)) { + case EM_386: + case EM_AARCH64: + case EM_LOONGARCH: +@@ -318,14 +323,14 @@ static int do_file(char const *const fna + break; + default: + fprintf(stderr, "unrecognized e_machine %d %s\n", +- r2(&ehdr->e_machine), fname); ++ r2(&ehdr->e32.e_machine), fname); + return -1; + } + +- switch (ehdr->e_ident[EI_CLASS]) { ++ switch (ehdr->e32.e_ident[EI_CLASS]) { + case ELFCLASS32: +- if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) || +- r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { ++ if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) || ++ r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) { + fprintf(stderr, + "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); + break; +@@ -334,20 +339,19 @@ static int do_file(char const *const fna + break; + case ELFCLASS64: + { +- Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; +- if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) || +- r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { ++ if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) || ++ r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) { + fprintf(stderr, + "unrecognized ET_EXEC/ET_DYN file: %s\n", + fname); + break; + } +- rc = do_sort_64(ghdr, fname, custom_sort); ++ rc = do_sort_64(ehdr, fname, custom_sort); + } + break; + default: + fprintf(stderr, "unrecognized ELF class %d %s\n", +- ehdr->e_ident[EI_CLASS], fname); ++ ehdr->e32.e_ident[EI_CLASS], fname); + break; + } + +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -23,12 +23,12 @@ + #undef sort_mcount_loc + #undef elf_mcount_loc + #undef do_sort +-#undef Elf_Ehdr + #undef Elf_Shdr + #undef Elf_Sym + #undef ELF_ST_TYPE + #undef uint_t + #undef _r ++#undef etype + + #ifdef SORTTABLE_64 + # define extable_ent_size 16 +@@ -37,12 +37,12 @@ + # define sort_mcount_loc sort_mcount_loc_64 + # define elf_mcount_loc elf_mcount_loc_64 + # define do_sort do_sort_64 +-# define Elf_Ehdr Elf64_Ehdr + # define Elf_Shdr Elf64_Shdr + # define Elf_Sym Elf64_Sym + # define ELF_ST_TYPE ELF64_ST_TYPE + # define uint_t uint64_t + # define _r r8 ++# define etype e64 + #else + # define extable_ent_size 8 + # define compare_extable compare_extable_32 +@@ -50,12 +50,12 @@ + # define sort_mcount_loc sort_mcount_loc_32 + # define elf_mcount_loc elf_mcount_loc_32 + # define do_sort do_sort_32 +-# define Elf_Ehdr Elf32_Ehdr + # define Elf_Shdr Elf32_Shdr + # define Elf_Sym Elf32_Sym + # define ELF_ST_TYPE ELF32_ST_TYPE + # define uint_t uint32_t + # define _r r ++# define etype e32 + #endif + + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +@@ -222,7 +222,7 @@ static int do_sort(Elf_Ehdr *ehdr, + table_sort_t custom_sort) + { + int rc = -1; +- Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); ++ Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff)); + Elf_Shdr *strtab_sec = NULL; + Elf_Shdr *symtab_sec = NULL; + Elf_Shdr *extab_sec = NULL; +@@ -249,12 +249,12 @@ static int do_sort(Elf_Ehdr *ehdr, + unsigned int orc_num_entries = 0; + #endif + +- shstrndx = r2(&ehdr->e_shstrndx); ++ shstrndx = r2(&ehdr->etype.e_shstrndx); + if (shstrndx == SHN_XINDEX) + shstrndx = r(&shdr[0].sh_link); + secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset); + +- shnum = r2(&ehdr->e_shnum); ++ shnum = r2(&ehdr->etype.e_shnum); + if (shnum == SHN_UNDEF) + shnum = _r(&shdr[0].sh_size); + diff --git a/queue-6.6/scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch b/queue-6.6/scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch new file mode 100644 index 0000000000..09e58cb3b5 --- /dev/null +++ b/queue-6.6/scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch @@ -0,0 +1,137 @@ +From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:39:22 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:46 -0400 +Subject: scripts/sorttable: Convert Elf_Sym MACRO over to a union +To: +Cc: , , , , , +Message-ID: <022a39638970364f156f71d69a7d77d8557fcd11.1781814109.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 200d015e73b4da69bcd8212a7c58695452b12bad ] + +In order to remove the double #include of sorttable.h for 64 and 32 bit +to create duplicate functions for both, replace the Elf_Sym macro with a +union that defines both Elf64_Sym and Elf32_Sym, with field e64 for the +64bit version, and e32 for the 32bit version. + +It can then use the macro etype to get the proper value. + +This will eventually be replaced with just single functions that can +handle both 32bit and 64bit ELF parsing. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162345.528626969@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 5 +++++ + scripts/sorttable.h | 25 ++++++++++++++----------- + 2 files changed, 19 insertions(+), 11 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -74,6 +74,11 @@ typedef union { + Elf64_Shdr e64; + } Elf_Shdr; + ++typedef union { ++ Elf32_Sym e32; ++ Elf64_Sym e64; ++} Elf_Sym; ++ + static uint32_t (*r)(const uint32_t *); + static uint16_t (*r2)(const uint16_t *); + static uint64_t (*r8)(const uint64_t *); +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -23,7 +23,6 @@ + #undef sort_mcount_loc + #undef elf_mcount_loc + #undef do_sort +-#undef Elf_Sym + #undef ELF_ST_TYPE + #undef uint_t + #undef _r +@@ -36,7 +35,6 @@ + # define sort_mcount_loc sort_mcount_loc_64 + # define elf_mcount_loc elf_mcount_loc_64 + # define do_sort do_sort_64 +-# define Elf_Sym Elf64_Sym + # define ELF_ST_TYPE ELF64_ST_TYPE + # define uint_t uint64_t + # define _r r8 +@@ -48,7 +46,6 @@ + # define sort_mcount_loc sort_mcount_loc_32 + # define elf_mcount_loc elf_mcount_loc_32 + # define do_sort do_sort_32 +-# define Elf_Sym Elf32_Sym + # define ELF_ST_TYPE ELF32_ST_TYPE + # define uint_t uint32_t + # define _r r +@@ -230,10 +227,13 @@ static int do_sort(Elf_Ehdr *ehdr, + Elf_Sym *sort_needed_sym = NULL; + Elf_Shdr *sort_needed_sec; + uint32_t *sort_needed_loc; ++ void *sym_start; ++ void *sym_end; + const char *secstrings; + const char *strtab; + char *extab_image; + int sort_need_index; ++ int symentsize; + int shentsize; + int idx; + int i; +@@ -376,12 +376,15 @@ static int do_sort(Elf_Ehdr *ehdr, + } + + /* find the flag main_extable_sort_needed */ +- for (sym = (void *)ehdr + _r(&symtab_sec->etype.sh_offset); +- sym < sym + _r(&symtab_sec->etype.sh_size) / sizeof(Elf_Sym); +- sym++) { +- if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) ++ sym_start = (void *)ehdr + _r(&symtab_sec->etype.sh_offset); ++ sym_end = sym_start + _r(&symtab_sec->etype.sh_size); ++ symentsize = _r(&symtab_sec->etype.sh_entsize); ++ ++ for (sym = sym_start; (void *)sym + symentsize < sym_end; ++ sym = (void *)sym + symentsize) { ++ if (ELF_ST_TYPE(sym->etype.st_info) != STT_OBJECT) + continue; +- if (!strcmp(strtab + r(&sym->st_name), ++ if (!strcmp(strtab + r(&sym->etype.st_name), + "main_extable_sort_needed")) { + sort_needed_sym = sym; + break; +@@ -395,13 +398,13 @@ static int do_sort(Elf_Ehdr *ehdr, + goto out; + } + +- sort_need_index = get_secindex(r2(&sym->st_shndx), +- sort_needed_sym - symtab, ++ sort_need_index = get_secindex(r2(&sym->etype.st_shndx), ++ ((void *)sort_needed_sym - (void *)symtab) / symentsize, + symtab_shndx); + sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index); + sort_needed_loc = (void *)ehdr + + _r(&sort_needed_sec->etype.sh_offset) + +- _r(&sort_needed_sym->st_value) - ++ _r(&sort_needed_sym->etype.st_value) - + _r(&sort_needed_sec->etype.sh_addr); + + /* extable has been sorted, clear the flag */ diff --git a/queue-6.6/scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch b/queue-6.6/scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch new file mode 100644 index 0000000000..ac7ac281f9 --- /dev/null +++ b/queue-6.6/scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch @@ -0,0 +1,51 @@ +From stable+bounces-267263-greg=kroah.com@vger.kernel.org Thu Jun 18 21:40:40 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:39:05 -0400 +Subject: scripts/sorttable: Fix endianness handling in build-time mcount sort +To: +Cc: , , , , , +Message-ID: <40e18ce8560e09cbc617451d9bc70586a8e013e2.1781814167.git.andrey.grodzovsky@crowdstrike.com> + +From: Vasily Gorbik + +[ Upstream commit 023f124a64174c47e18340ded7e2a39b96eb9523 ] + +Kernel cross-compilation with BUILDTIME_MCOUNT_SORT produces zeroed +mcount values if the build-host endianness does not match the ELF +file endianness. + +The mcount values array is converted from ELF file +endianness to build-host endianness during initialization in +fill_relocs()/fill_addrs(). Avoid extra conversion of these values during +weak-function zeroing; otherwise, they do not match nm-parsed addresses +and all mcount values are zeroed out. + +Cc: Masami Hiramatsu +Cc: Catalin Marinas +Cc: Nathan Chancellor +Cc: Heiko Carstens +Cc: Alexander Gordeev +Link: https://lore.kernel.org/patch.git-dca31444b0f1.your-ad-here.call-01743554658-ext-8692@work.hours +Fixes: ef378c3b8233 ("scripts/sorttable: Zero out weak functions in mcount_loc table") +Reported-by: Ilya Leoshkevich +Reported-by: Ihor Solodrai +Closes: https://lore.kernel.org/all/your-ad-here.call-01743522822-ext-4975@work.hours/ +Signed-off-by: Vasily Gorbik +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -857,7 +857,7 @@ static void *sort_mcount_loc(void *arg) + 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); ++ key = long_size == 4 ? *(uint32_t *)ptr : *(uint64_t *)ptr; + if (!find_func(key)) { + if (long_size == 4) + *(uint32_t *)ptr = 0; diff --git a/queue-6.6/scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch b/queue-6.6/scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch new file mode 100644 index 0000000000..d9a54ce48d --- /dev/null +++ b/queue-6.6/scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch @@ -0,0 +1,192 @@ +From stable+bounces-267249-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:37 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:52 -0400 +Subject: scripts/sorttable: Get start/stop_mcount_loc from ELF file directly +To: +Cc: , , , , , +Message-ID: <38775b36f85b8e49dbea5c6491b50ce10d298691.1781814129.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 4acda8edefa1ce66d3de845f1c12745721cd14c3 ] + +The get_mcount_loc() does a cheesy trick to find the start_mcount_loc and +stop_mcount_loc values. That trick is: + + file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r"); + +and + + file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r"); + +Those values are stored in the Elf symbol table. Use that to capture those +values. Using the symbol table is more efficient and more robust. The +above could fail if another variable had "start_mcount" or "stop_mcount" +as part of its name. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162346.817157047@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 95 ++++++++++++++++++++++++---------------------------- + 1 file changed, 45 insertions(+), 50 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -472,42 +472,41 @@ static void *sort_mcount_loc(void *arg) + } + + /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */ +-static void get_mcount_loc(uint64_t *_start, uint64_t *_stop) ++static void get_mcount_loc(struct elf_mcount_loc *emloc, Elf_Shdr *symtab_sec, ++ const char *strtab) + { +- FILE *file_start, *file_stop; +- char start_buff[20]; +- char stop_buff[20]; +- int len = 0; ++ Elf_Sym *sym, *end_sym; ++ int symentsize = shdr_entsize(symtab_sec); ++ int found = 0; ++ ++ sym = (void *)emloc->ehdr + shdr_offset(symtab_sec); ++ end_sym = (void *)sym + shdr_size(symtab_sec); ++ ++ while (sym < end_sym) { ++ if (!strcmp(strtab + sym_name(sym), "__start_mcount_loc")) { ++ emloc->start_mcount_loc = sym_value(sym); ++ if (++found == 2) ++ break; ++ } else if (!strcmp(strtab + sym_name(sym), "__stop_mcount_loc")) { ++ emloc->stop_mcount_loc = sym_value(sym); ++ if (++found == 2) ++ break; ++ } ++ sym = (void *)sym + symentsize; ++ } + +- file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r"); +- if (!file_start) { ++ if (!emloc->start_mcount_loc) { + fprintf(stderr, "get start_mcount_loc error!"); + return; + } + +- file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r"); +- if (!file_stop) { ++ if (!emloc->stop_mcount_loc) { + fprintf(stderr, "get stop_mcount_loc error!"); +- pclose(file_start); + return; + } +- +- while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) { +- len = strlen(start_buff); +- start_buff[len - 1] = '\0'; +- } +- *_start = strtoul(start_buff, NULL, 16); +- +- while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) { +- len = strlen(stop_buff); +- stop_buff[len - 1] = '\0'; +- } +- *_stop = strtoul(stop_buff, NULL, 16); +- +- pclose(file_start); +- pclose(file_stop); + } + #endif ++ + static int do_sort(Elf_Ehdr *ehdr, + char const *const fname, + table_sort_t custom_sort) +@@ -538,8 +537,6 @@ static int do_sort(Elf_Ehdr *ehdr, + unsigned int shstrndx; + #ifdef MCOUNT_SORT_ENABLED + struct elf_mcount_loc mstruct = {0}; +- uint64_t _start_mcount_loc = 0; +- uint64_t _stop_mcount_loc = 0; + #endif + #ifdef UNWINDER_ORC_ENABLED + unsigned int orc_ip_size = 0; +@@ -577,13 +574,8 @@ static int do_sort(Elf_Ehdr *ehdr, + + #ifdef MCOUNT_SORT_ENABLED + /* locate the .init.data section in vmlinux */ +- if (!strcmp(secstrings + idx, ".init.data")) { +- get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc); +- mstruct.ehdr = ehdr; ++ if (!strcmp(secstrings + idx, ".init.data")) + mstruct.init_data_sec = shdr; +- mstruct.start_mcount_loc = _start_mcount_loc; +- mstruct.stop_mcount_loc = _stop_mcount_loc; +- } + #endif + + #ifdef UNWINDER_ORC_ENABLED +@@ -627,23 +619,6 @@ static int do_sort(Elf_Ehdr *ehdr, + goto out; + } + #endif +- +-#ifdef MCOUNT_SORT_ENABLED +- if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) { +- fprintf(stderr, +- "incomplete mcount's sort in file: %s\n", +- fname); +- goto out; +- } +- +- /* create thread to sort mcount_loc concurrently */ +- if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) { +- fprintf(stderr, +- "pthread_create mcount_sort_thread failed '%s': %s\n", +- strerror(errno), fname); +- goto out; +- } +-#endif + if (!extab_sec) { + fprintf(stderr, "no __ex_table in file: %s\n", fname); + goto out; +@@ -663,6 +638,26 @@ static int do_sort(Elf_Ehdr *ehdr, + strtab = (const char *)ehdr + shdr_offset(strtab_sec); + symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec)); + ++#ifdef MCOUNT_SORT_ENABLED ++ mstruct.ehdr = ehdr; ++ get_mcount_loc(&mstruct, symtab_sec, strtab); ++ ++ if (!mstruct.init_data_sec || !mstruct.start_mcount_loc || !mstruct.stop_mcount_loc) { ++ fprintf(stderr, ++ "incomplete mcount's sort in file: %s\n", ++ fname); ++ goto out; ++ } ++ ++ /* create thread to sort mcount_loc concurrently */ ++ if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) { ++ fprintf(stderr, ++ "pthread_create mcount_sort_thread failed '%s': %s\n", ++ strerror(errno), fname); ++ goto out; ++ } ++#endif ++ + if (custom_sort) { + custom_sort(extab_image, shdr_size(extab_sec)); + } else { diff --git a/queue-6.6/scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch b/queue-6.6/scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch new file mode 100644 index 0000000000..42eef82746 --- /dev/null +++ b/queue-6.6/scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch @@ -0,0 +1,100 @@ +From stable+bounces-267253-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:46 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:55 -0400 +Subject: scripts/sorttable: Have mcount rela sort use direct values +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit a0265659322540d656727b9e132edfb6f06b6c1a ] + +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. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Heiko Carstens +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Vasily Gorbik +Cc: Alexander Gordeev +Link: https://lore.kernel.org/20250218200022.538888594@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +--- 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, + 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, + } + } + 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++) { diff --git a/queue-6.6/scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch b/queue-6.6/scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch new file mode 100644 index 0000000000..a945c5631a --- /dev/null +++ b/queue-6.6/scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch @@ -0,0 +1,61 @@ +From stable+bounces-267242-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:28 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:42 -0400 +Subject: scripts/sorttable: Have the ORC code use the _r() functions to read +To: +Cc: , , , , , +Message-ID: <50048eb4cf1919493585ba6beb29fa8822c1b37f.1781814096.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 66990c003306c240d570b3ba274ec4f68cf18c91 ] + +The ORC code reads the section information directly from the file. This +currently works because the default read function is for 64bit little +endian machines. But if for some reason that ever changes, this will +break. Instead of having a surprise breakage, use the _r() functions that +will read the values from the file properly. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162344.721480386@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -299,14 +299,14 @@ static int do_sort(Elf_Ehdr *ehdr, + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + /* locate the ORC unwind tables */ + if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { +- orc_ip_size = s->sh_size; ++ orc_ip_size = _r(&s->sh_size); + g_orc_ip_table = (int *)((void *)ehdr + +- s->sh_offset); ++ _r(&s->sh_offset)); + } + if (!strcmp(secstrings + idx, ".orc_unwind")) { +- orc_size = s->sh_size; ++ orc_size = _r(&s->sh_size); + g_orc_table = (struct orc_entry *)((void *)ehdr + +- s->sh_offset); ++ _r(&s->sh_offset)); + } + #endif + } /* for loop */ diff --git a/queue-6.6/scripts-sorttable-make-compare_extable-into-two-functions.patch b/queue-6.6/scripts-sorttable-make-compare_extable-into-two-functions.patch new file mode 100644 index 0000000000..65f50ddc6f --- /dev/null +++ b/queue-6.6/scripts-sorttable-make-compare_extable-into-two-functions.patch @@ -0,0 +1,128 @@ +From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:39:18 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:43 -0400 +Subject: scripts/sorttable: Make compare_extable() into two functions +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit 7ffc0d0819f438779ed592e2e2e3576f43ce14f0 ] + +Instead of having the compare_extable() part of the sorttable.h header +where it get's defined twice, since it is a very simple function, just +define it twice in sorttable.c, and then it can use the proper read +functions for the word size and endianess and the Elf_Addr macro can be +removed from sorttable.h. + +Also add a micro optimization. Instead of: + + if (a < b) + return -1; + if (a > b) + return 1; + return 0; + +That can be shorten to: + + if (a < b) + return -1; + return a > b; + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162344.945299671@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 20 ++++++++++++++++++++ + scripts/sorttable.h | 14 -------------- + 2 files changed, 20 insertions(+), 14 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -173,6 +173,26 @@ static inline unsigned int get_secindex( + return r(&symtab_shndx_start[sym_offs]); + } + ++static int compare_extable_32(const void *a, const void *b) ++{ ++ Elf32_Addr av = r(a); ++ Elf32_Addr bv = r(b); ++ ++ if (av < bv) ++ return -1; ++ return av > bv; ++} ++ ++static int compare_extable_64(const void *a, const void *b) ++{ ++ Elf64_Addr av = r8(a); ++ Elf64_Addr bv = r8(b); ++ ++ if (av < bv) ++ return -1; ++ return av > bv; ++} ++ + /* 32 bit and 64 bit are very similar */ + #include "sorttable.h" + #define SORTTABLE_64 +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -23,7 +23,6 @@ + #undef sort_mcount_loc + #undef elf_mcount_loc + #undef do_sort +-#undef Elf_Addr + #undef Elf_Ehdr + #undef Elf_Shdr + #undef Elf_Sym +@@ -38,7 +37,6 @@ + # define sort_mcount_loc sort_mcount_loc_64 + # define elf_mcount_loc elf_mcount_loc_64 + # define do_sort do_sort_64 +-# define Elf_Addr Elf64_Addr + # define Elf_Ehdr Elf64_Ehdr + # define Elf_Shdr Elf64_Shdr + # define Elf_Sym Elf64_Sym +@@ -52,7 +50,6 @@ + # define sort_mcount_loc sort_mcount_loc_32 + # define elf_mcount_loc elf_mcount_loc_32 + # define do_sort do_sort_32 +-# define Elf_Addr Elf32_Addr + # define Elf_Ehdr Elf32_Ehdr + # define Elf_Shdr Elf32_Shdr + # define Elf_Sym Elf32_Sym +@@ -160,17 +157,6 @@ static void *sort_orctable(void *arg) + } + #endif + +-static int compare_extable(const void *a, const void *b) +-{ +- Elf_Addr av = _r(a); +- Elf_Addr bv = _r(b); +- +- if (av < bv) +- return -1; +- if (av > bv) +- return 1; +- return 0; +-} + #ifdef MCOUNT_SORT_ENABLED + pthread_t mcount_sort_thread; + diff --git a/queue-6.6/scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch b/queue-6.6/scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch new file mode 100644 index 0000000000..eca86822ff --- /dev/null +++ b/queue-6.6/scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch @@ -0,0 +1,1051 @@ +From stable+bounces-267250-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:39 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:51 -0400 +Subject: scripts/sorttable: Move code from sorttable.h into sorttable.c +To: +Cc: , , , , , +Message-ID: <3b26fdb0cd9f5e8ac6569f4aca0bfd92731a0c17.1781814126.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 58d87678a0f46c6120904b4326aaf5ebf4454c69 ] + +Instead of having the main code live in a header file and included twice +with MACROs that define the Elf structures for 64 bit or 32 bit, move the +code in the C file now that the Elf structures are defined in a union that +has both. All accesses to the Elf structure fields are done through helper +function pointers. If the file being parsed if for a 64 bit architecture, +all the helper functions point to the 64 bit versions to retrieve the Elf +fields. The same is true if the architecture is 32 bit, where the function +pointers will point to the 32 bit helper functions. + +Note, when the value of a field can be either 32 bit or 64 bit, a 64 bit +is always returned, as it works for the 32 bit code as well. + +This makes the code easier to read and maintain, and it now all exists in +sorttable.c and sorttable.h may be removed. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Stephen Rothwell +Link: https://lore.kernel.org/20250107223217.6f7f96a5@gandalf.local.home +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 473 +++++++++++++++++++++++++++++++++++++++++++++++++- + scripts/sorttable.h | 485 ---------------------------------------------------- + 2 files changed, 460 insertions(+), 498 deletions(-) + delete mode 100644 scripts/sorttable.h + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -327,10 +327,423 @@ static inline void *get_index(void *star + return start + (entsize * index); + } + +-/* 32 bit and 64 bit are very similar */ +-#include "sorttable.h" +-#define SORTTABLE_64 +-#include "sorttable.h" ++ ++static int (*compare_extable)(const void *a, const void *b); ++static uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr); ++static uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr); ++static uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr); ++static uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr); ++static uint64_t (*shdr_addr)(Elf_Shdr *shdr); ++static uint64_t (*shdr_offset)(Elf_Shdr *shdr); ++static uint64_t (*shdr_size)(Elf_Shdr *shdr); ++static uint64_t (*shdr_entsize)(Elf_Shdr *shdr); ++static uint32_t (*shdr_link)(Elf_Shdr *shdr); ++static uint32_t (*shdr_name)(Elf_Shdr *shdr); ++static uint32_t (*shdr_type)(Elf_Shdr *shdr); ++static uint8_t (*sym_type)(Elf_Sym *sym); ++static uint32_t (*sym_name)(Elf_Sym *sym); ++static uint64_t (*sym_value)(Elf_Sym *sym); ++static uint16_t (*sym_shndx)(Elf_Sym *sym); ++ ++static int extable_ent_size; ++static int long_size; ++ ++ ++#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; ++ ++static pthread_t orc_sort_thread; ++ ++static inline unsigned long orc_ip(const int *ip) ++{ ++ return (unsigned long)ip + *ip; ++} ++ ++static int orc_sort_cmp(const void *_a, const void *_b) ++{ ++ struct orc_entry *orc_a, *orc_b; ++ const int *a = g_orc_ip_table + *(int *)_a; ++ const int *b = g_orc_ip_table + *(int *)_b; ++ unsigned long a_val = orc_ip(a); ++ unsigned long b_val = orc_ip(b); ++ ++ if (a_val > b_val) ++ return 1; ++ if (a_val < b_val) ++ return -1; ++ ++ /* ++ * The "weak" section terminator entries need to always be on the left ++ * to ensure the lookup code skips them in favor of real entries. ++ * These terminator entries exist to handle any gaps created by ++ * whitelisted .o files which didn't get objtool generation. ++ */ ++ orc_a = g_orc_table + (a - g_orc_ip_table); ++ orc_b = g_orc_table + (b - g_orc_ip_table); ++ if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED) ++ return 0; ++ return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1; ++} ++ ++static void *sort_orctable(void *arg) ++{ ++ int i; ++ int *idxs = NULL; ++ int *tmp_orc_ip_table = NULL; ++ struct orc_entry *tmp_orc_table = NULL; ++ unsigned int *orc_ip_size = (unsigned int *)arg; ++ unsigned int num_entries = *orc_ip_size / sizeof(int); ++ unsigned int orc_size = num_entries * sizeof(struct orc_entry); ++ ++ idxs = (int *)malloc(*orc_ip_size); ++ if (!idxs) { ++ snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s", ++ strerror(errno)); ++ pthread_exit(g_err); ++ } ++ ++ tmp_orc_ip_table = (int *)malloc(*orc_ip_size); ++ if (!tmp_orc_ip_table) { ++ snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s", ++ strerror(errno)); ++ pthread_exit(g_err); ++ } ++ ++ tmp_orc_table = (struct orc_entry *)malloc(orc_size); ++ if (!tmp_orc_table) { ++ snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s", ++ strerror(errno)); ++ pthread_exit(g_err); ++ } ++ ++ /* initialize indices array, convert ip_table to absolute address */ ++ for (i = 0; i < num_entries; i++) { ++ idxs[i] = i; ++ tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int); ++ } ++ memcpy(tmp_orc_table, g_orc_table, orc_size); ++ ++ qsort(idxs, num_entries, sizeof(int), orc_sort_cmp); ++ ++ for (i = 0; i < num_entries; i++) { ++ if (idxs[i] == i) ++ continue; ++ ++ /* convert back to relative address */ ++ g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int); ++ g_orc_table[i] = tmp_orc_table[idxs[i]]; ++ } ++ ++ free(idxs); ++ free(tmp_orc_ip_table); ++ free(tmp_orc_table); ++ pthread_exit(NULL); ++} ++#endif ++ ++#ifdef MCOUNT_SORT_ENABLED ++static pthread_t mcount_sort_thread; ++ ++struct elf_mcount_loc { ++ Elf_Ehdr *ehdr; ++ Elf_Shdr *init_data_sec; ++ uint64_t start_mcount_loc; ++ uint64_t stop_mcount_loc; ++}; ++ ++/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */ ++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; ++ unsigned char *start_loc = (void *)emloc->ehdr + offset; ++ ++ qsort(start_loc, count/long_size, long_size, compare_extable); ++ return NULL; ++} ++ ++/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */ ++static void get_mcount_loc(uint64_t *_start, uint64_t *_stop) ++{ ++ FILE *file_start, *file_stop; ++ char start_buff[20]; ++ char stop_buff[20]; ++ int len = 0; ++ ++ file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r"); ++ if (!file_start) { ++ fprintf(stderr, "get start_mcount_loc error!"); ++ return; ++ } ++ ++ file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r"); ++ if (!file_stop) { ++ fprintf(stderr, "get stop_mcount_loc error!"); ++ pclose(file_start); ++ return; ++ } ++ ++ while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) { ++ len = strlen(start_buff); ++ start_buff[len - 1] = '\0'; ++ } ++ *_start = strtoul(start_buff, NULL, 16); ++ ++ while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) { ++ len = strlen(stop_buff); ++ stop_buff[len - 1] = '\0'; ++ } ++ *_stop = strtoul(stop_buff, NULL, 16); ++ ++ pclose(file_start); ++ pclose(file_stop); ++} ++#endif ++static int do_sort(Elf_Ehdr *ehdr, ++ char const *const fname, ++ table_sort_t custom_sort) ++{ ++ int rc = -1; ++ Elf_Shdr *shdr_start; ++ Elf_Shdr *strtab_sec = NULL; ++ Elf_Shdr *symtab_sec = NULL; ++ Elf_Shdr *extab_sec = NULL; ++ Elf_Shdr *string_sec; ++ Elf_Sym *sym; ++ const Elf_Sym *symtab; ++ Elf32_Word *symtab_shndx = NULL; ++ Elf_Sym *sort_needed_sym = NULL; ++ Elf_Shdr *sort_needed_sec; ++ uint32_t *sort_needed_loc; ++ void *sym_start; ++ void *sym_end; ++ const char *secstrings; ++ const char *strtab; ++ char *extab_image; ++ int sort_need_index; ++ int symentsize; ++ int shentsize; ++ int idx; ++ int i; ++ unsigned int shnum; ++ unsigned int shstrndx; ++#ifdef MCOUNT_SORT_ENABLED ++ struct elf_mcount_loc mstruct = {0}; ++ uint64_t _start_mcount_loc = 0; ++ uint64_t _stop_mcount_loc = 0; ++#endif ++#ifdef UNWINDER_ORC_ENABLED ++ unsigned int orc_ip_size = 0; ++ unsigned int orc_size = 0; ++ unsigned int orc_num_entries = 0; ++#endif ++ ++ shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); ++ shentsize = ehdr_shentsize(ehdr); ++ ++ shstrndx = ehdr_shstrndx(ehdr); ++ if (shstrndx == SHN_XINDEX) ++ shstrndx = shdr_link(shdr_start); ++ string_sec = get_index(shdr_start, shentsize, shstrndx); ++ secstrings = (const char *)ehdr + shdr_offset(string_sec); ++ ++ shnum = ehdr_shnum(ehdr); ++ if (shnum == SHN_UNDEF) ++ shnum = shdr_size(shdr_start); ++ ++ for (i = 0; i < shnum; i++) { ++ Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); ++ ++ idx = shdr_name(shdr); ++ if (!strcmp(secstrings + idx, "__ex_table")) ++ extab_sec = shdr; ++ if (!strcmp(secstrings + idx, ".symtab")) ++ symtab_sec = shdr; ++ if (!strcmp(secstrings + idx, ".strtab")) ++ strtab_sec = shdr; ++ ++ if (shdr_type(shdr) == SHT_SYMTAB_SHNDX) ++ symtab_shndx = (Elf32_Word *)((const char *)ehdr + ++ shdr_offset(shdr)); ++ ++#ifdef MCOUNT_SORT_ENABLED ++ /* locate the .init.data section in vmlinux */ ++ if (!strcmp(secstrings + idx, ".init.data")) { ++ get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc); ++ mstruct.ehdr = ehdr; ++ mstruct.init_data_sec = shdr; ++ mstruct.start_mcount_loc = _start_mcount_loc; ++ mstruct.stop_mcount_loc = _stop_mcount_loc; ++ } ++#endif ++ ++#ifdef UNWINDER_ORC_ENABLED ++ /* locate the ORC unwind tables */ ++ if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { ++ orc_ip_size = shdr_size(shdr); ++ g_orc_ip_table = (int *)((void *)ehdr + ++ shdr_offset(shdr)); ++ } ++ if (!strcmp(secstrings + idx, ".orc_unwind")) { ++ orc_size = shdr_size(shdr); ++ g_orc_table = (struct orc_entry *)((void *)ehdr + ++ shdr_offset(shdr)); ++ } ++#endif ++ } /* for loop */ ++ ++#ifdef UNWINDER_ORC_ENABLED ++ if (!g_orc_ip_table || !g_orc_table) { ++ fprintf(stderr, ++ "incomplete ORC unwind tables in file: %s\n", fname); ++ goto out; ++ } ++ ++ orc_num_entries = orc_ip_size / sizeof(int); ++ if (orc_ip_size % sizeof(int) != 0 || ++ orc_size % sizeof(struct orc_entry) != 0 || ++ orc_num_entries != orc_size / sizeof(struct orc_entry)) { ++ fprintf(stderr, ++ "inconsistent ORC unwind table entries in file: %s\n", ++ fname); ++ goto out; ++ } ++ ++ /* create thread to sort ORC unwind tables concurrently */ ++ if (pthread_create(&orc_sort_thread, NULL, ++ sort_orctable, &orc_ip_size)) { ++ fprintf(stderr, ++ "pthread_create orc_sort_thread failed '%s': %s\n", ++ strerror(errno), fname); ++ goto out; ++ } ++#endif ++ ++#ifdef MCOUNT_SORT_ENABLED ++ if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) { ++ fprintf(stderr, ++ "incomplete mcount's sort in file: %s\n", ++ fname); ++ goto out; ++ } ++ ++ /* create thread to sort mcount_loc concurrently */ ++ if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) { ++ fprintf(stderr, ++ "pthread_create mcount_sort_thread failed '%s': %s\n", ++ strerror(errno), fname); ++ goto out; ++ } ++#endif ++ if (!extab_sec) { ++ fprintf(stderr, "no __ex_table in file: %s\n", fname); ++ goto out; ++ } ++ ++ if (!symtab_sec) { ++ fprintf(stderr, "no .symtab in file: %s\n", fname); ++ goto out; ++ } ++ ++ if (!strtab_sec) { ++ fprintf(stderr, "no .strtab in file: %s\n", fname); ++ goto out; ++ } ++ ++ extab_image = (void *)ehdr + shdr_offset(extab_sec); ++ strtab = (const char *)ehdr + shdr_offset(strtab_sec); ++ symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec)); ++ ++ if (custom_sort) { ++ custom_sort(extab_image, shdr_size(extab_sec)); ++ } else { ++ int num_entries = shdr_size(extab_sec) / extable_ent_size; ++ qsort(extab_image, num_entries, ++ extable_ent_size, compare_extable); ++ } ++ ++ /* find the flag main_extable_sort_needed */ ++ sym_start = (void *)ehdr + shdr_offset(symtab_sec); ++ sym_end = sym_start + shdr_size(symtab_sec); ++ symentsize = shdr_entsize(symtab_sec); ++ ++ for (sym = sym_start; (void *)sym + symentsize < sym_end; ++ sym = (void *)sym + symentsize) { ++ if (sym_type(sym) != STT_OBJECT) ++ continue; ++ if (!strcmp(strtab + sym_name(sym), ++ "main_extable_sort_needed")) { ++ sort_needed_sym = sym; ++ break; ++ } ++ } ++ ++ if (!sort_needed_sym) { ++ fprintf(stderr, ++ "no main_extable_sort_needed symbol in file: %s\n", ++ fname); ++ goto out; ++ } ++ ++ sort_need_index = get_secindex(sym_shndx(sym), ++ ((void *)sort_needed_sym - (void *)symtab) / symentsize, ++ symtab_shndx); ++ sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index); ++ sort_needed_loc = (void *)ehdr + ++ shdr_offset(sort_needed_sec) + ++ sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec); ++ ++ /* extable has been sorted, clear the flag */ ++ w(0, sort_needed_loc); ++ rc = 0; ++ ++out: ++#ifdef UNWINDER_ORC_ENABLED ++ if (orc_sort_thread) { ++ void *retval = NULL; ++ /* wait for ORC tables sort done */ ++ rc = pthread_join(orc_sort_thread, &retval); ++ if (rc) { ++ fprintf(stderr, ++ "pthread_join failed '%s': %s\n", ++ strerror(errno), fname); ++ } else if (retval) { ++ rc = -1; ++ fprintf(stderr, ++ "failed to sort ORC tables '%s': %s\n", ++ (char *)retval, fname); ++ } ++ } ++#endif ++ ++#ifdef MCOUNT_SORT_ENABLED ++ if (mcount_sort_thread) { ++ void *retval = NULL; ++ /* wait for mcount sort done */ ++ rc = pthread_join(mcount_sort_thread, &retval); ++ if (rc) { ++ fprintf(stderr, ++ "pthread_join failed '%s': %s\n", ++ strerror(errno), fname); ++ } else if (retval) { ++ rc = -1; ++ fprintf(stderr, ++ "failed to sort mcount '%s': %s\n", ++ (char *)retval, fname); ++ } ++ } ++#endif ++ return rc; ++} + + static int compare_relative_table(const void *a, const void *b) + { +@@ -399,7 +812,6 @@ static void sort_relative_table_with_dat + + static int do_file(char const *const fname, void *addr) + { +- int rc = -1; + Elf_Ehdr *ehdr = addr; + table_sort_t custom_sort = NULL; + +@@ -462,29 +874,64 @@ static int do_file(char const *const fna + r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) { + fprintf(stderr, + "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); +- break; ++ return -1; + } +- rc = do_sort_32(ehdr, fname, custom_sort); ++ ++ compare_extable = compare_extable_32; ++ ehdr_shoff = ehdr32_shoff; ++ ehdr_shentsize = ehdr32_shentsize; ++ ehdr_shstrndx = ehdr32_shstrndx; ++ ehdr_shnum = ehdr32_shnum; ++ shdr_addr = shdr32_addr; ++ shdr_offset = shdr32_offset; ++ shdr_link = shdr32_link; ++ shdr_size = shdr32_size; ++ shdr_name = shdr32_name; ++ shdr_type = shdr32_type; ++ shdr_entsize = shdr32_entsize; ++ sym_type = sym32_type; ++ sym_name = sym32_name; ++ sym_value = sym32_value; ++ sym_shndx = sym32_shndx; ++ long_size = 4; ++ extable_ent_size = 8; + break; + case ELFCLASS64: +- { + if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) || + r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) { + fprintf(stderr, + "unrecognized ET_EXEC/ET_DYN file: %s\n", + fname); +- break; +- } +- rc = do_sort_64(ehdr, fname, custom_sort); ++ return -1; + } ++ ++ compare_extable = compare_extable_64; ++ ehdr_shoff = ehdr64_shoff; ++ ehdr_shentsize = ehdr64_shentsize; ++ ehdr_shstrndx = ehdr64_shstrndx; ++ ehdr_shnum = ehdr64_shnum; ++ shdr_addr = shdr64_addr; ++ shdr_offset = shdr64_offset; ++ shdr_link = shdr64_link; ++ shdr_size = shdr64_size; ++ shdr_name = shdr64_name; ++ shdr_type = shdr64_type; ++ shdr_entsize = shdr64_entsize; ++ sym_type = sym64_type; ++ sym_name = sym64_name; ++ sym_value = sym64_value; ++ sym_shndx = sym64_shndx; ++ long_size = 8; ++ extable_ent_size = 16; ++ + break; + default: + fprintf(stderr, "unrecognized ELF class %d %s\n", + ehdr->e32.e_ident[EI_CLASS], fname); +- break; ++ return -1; + } + +- return rc; ++ return do_sort(ehdr, fname, custom_sort); + } + + int main(int argc, char *argv[]) +--- a/scripts/sorttable.h ++++ /dev/null +@@ -1,485 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * sorttable.h +- * +- * Added ORC unwind tables sort support and other updates: +- * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by: +- * Shile Zhang +- * +- * Copyright 2011 - 2012 Cavium, Inc. +- * +- * Some of code was taken out of arch/x86/kernel/unwind_orc.c, written by: +- * Copyright (C) 2017 Josh Poimboeuf +- * +- * Some of this code was taken out of recordmcount.h written by: +- * +- * Copyright 2009 John F. Reiser . All rights reserved. +- * Copyright 2010 Steven Rostedt , Red Hat Inc. +- */ +- +-#undef extable_ent_size +-#undef compare_extable +-#undef get_mcount_loc +-#undef sort_mcount_loc +-#undef elf_mcount_loc +-#undef do_sort +-#undef ehdr_shoff +-#undef ehdr_shentsize +-#undef ehdr_shstrndx +-#undef ehdr_shnum +-#undef shdr_addr +-#undef shdr_offset +-#undef shdr_link +-#undef shdr_size +-#undef shdr_name +-#undef shdr_type +-#undef shdr_entsize +-#undef sym_type +-#undef sym_name +-#undef sym_value +-#undef sym_shndx +-#undef long_size +- +-#ifdef SORTTABLE_64 +-# define extable_ent_size 16 +-# define compare_extable compare_extable_64 +-# define get_mcount_loc get_mcount_loc_64 +-# define sort_mcount_loc sort_mcount_loc_64 +-# define elf_mcount_loc elf_mcount_loc_64 +-# define do_sort do_sort_64 +-# define ehdr_shoff ehdr64_shoff +-# define ehdr_shentsize ehdr64_shentsize +-# define ehdr_shstrndx ehdr64_shstrndx +-# define ehdr_shnum ehdr64_shnum +-# define shdr_addr shdr64_addr +-# define shdr_offset shdr64_offset +-# define shdr_link shdr64_link +-# define shdr_size shdr64_size +-# define shdr_name shdr64_name +-# define shdr_type shdr64_type +-# define shdr_entsize shdr64_entsize +-# define sym_type sym64_type +-# define sym_name sym64_name +-# define sym_value sym64_value +-# define sym_shndx sym64_shndx +-# define long_size 8 +-#else +-# define extable_ent_size 8 +-# define compare_extable compare_extable_32 +-# define get_mcount_loc get_mcount_loc_32 +-# define sort_mcount_loc sort_mcount_loc_32 +-# define elf_mcount_loc elf_mcount_loc_32 +-# define do_sort do_sort_32 +-# define ehdr_shoff ehdr32_shoff +-# define ehdr_shentsize ehdr32_shentsize +-# define ehdr_shstrndx ehdr32_shstrndx +-# define ehdr_shnum ehdr32_shnum +-# define shdr_addr shdr32_addr +-# define shdr_offset shdr32_offset +-# define shdr_link shdr32_link +-# define shdr_size shdr32_size +-# define shdr_name shdr32_name +-# define shdr_type shdr32_type +-# define shdr_entsize shdr32_entsize +-# define sym_type sym32_type +-# define sym_name sym32_name +-# define sym_value sym32_value +-# define sym_shndx sym32_shndx +-# define long_size 4 +-#endif +- +-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +-/* ORC unwinder only support X86_64 */ +-#include +- +-#define ERRSTR_MAXSZ 256 +- +-char g_err[ERRSTR_MAXSZ]; +-int *g_orc_ip_table; +-struct orc_entry *g_orc_table; +- +-pthread_t orc_sort_thread; +- +-static inline unsigned long orc_ip(const int *ip) +-{ +- return (unsigned long)ip + *ip; +-} +- +-static int orc_sort_cmp(const void *_a, const void *_b) +-{ +- struct orc_entry *orc_a, *orc_b; +- const int *a = g_orc_ip_table + *(int *)_a; +- const int *b = g_orc_ip_table + *(int *)_b; +- unsigned long a_val = orc_ip(a); +- unsigned long b_val = orc_ip(b); +- +- if (a_val > b_val) +- return 1; +- if (a_val < b_val) +- return -1; +- +- /* +- * The "weak" section terminator entries need to always be on the left +- * to ensure the lookup code skips them in favor of real entries. +- * These terminator entries exist to handle any gaps created by +- * whitelisted .o files which didn't get objtool generation. +- */ +- orc_a = g_orc_table + (a - g_orc_ip_table); +- orc_b = g_orc_table + (b - g_orc_ip_table); +- if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED) +- return 0; +- return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1; +-} +- +-static void *sort_orctable(void *arg) +-{ +- int i; +- int *idxs = NULL; +- int *tmp_orc_ip_table = NULL; +- struct orc_entry *tmp_orc_table = NULL; +- unsigned int *orc_ip_size = (unsigned int *)arg; +- unsigned int num_entries = *orc_ip_size / sizeof(int); +- unsigned int orc_size = num_entries * sizeof(struct orc_entry); +- +- idxs = (int *)malloc(*orc_ip_size); +- if (!idxs) { +- snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s", +- strerror(errno)); +- pthread_exit(g_err); +- } +- +- tmp_orc_ip_table = (int *)malloc(*orc_ip_size); +- if (!tmp_orc_ip_table) { +- snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s", +- strerror(errno)); +- pthread_exit(g_err); +- } +- +- tmp_orc_table = (struct orc_entry *)malloc(orc_size); +- if (!tmp_orc_table) { +- snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s", +- strerror(errno)); +- pthread_exit(g_err); +- } +- +- /* initialize indices array, convert ip_table to absolute address */ +- for (i = 0; i < num_entries; i++) { +- idxs[i] = i; +- tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int); +- } +- memcpy(tmp_orc_table, g_orc_table, orc_size); +- +- qsort(idxs, num_entries, sizeof(int), orc_sort_cmp); +- +- for (i = 0; i < num_entries; i++) { +- if (idxs[i] == i) +- continue; +- +- /* convert back to relative address */ +- g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int); +- g_orc_table[i] = tmp_orc_table[idxs[i]]; +- } +- +- free(idxs); +- free(tmp_orc_ip_table); +- free(tmp_orc_table); +- pthread_exit(NULL); +-} +-#endif +- +-#ifdef MCOUNT_SORT_ENABLED +-pthread_t mcount_sort_thread; +- +-struct elf_mcount_loc { +- Elf_Ehdr *ehdr; +- Elf_Shdr *init_data_sec; +- uint64_t start_mcount_loc; +- uint64_t stop_mcount_loc; +-}; +- +-/* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */ +-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; +- unsigned char *start_loc = (void *)emloc->ehdr + offset; +- +- qsort(start_loc, count/long_size, long_size, compare_extable); +- return NULL; +-} +- +-/* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */ +-static void get_mcount_loc(uint64_t *_start, uint64_t *_stop) +-{ +- FILE *file_start, *file_stop; +- char start_buff[20]; +- char stop_buff[20]; +- int len = 0; +- +- file_start = popen(" grep start_mcount System.map | awk '{print $1}' ", "r"); +- if (!file_start) { +- fprintf(stderr, "get start_mcount_loc error!"); +- return; +- } +- +- file_stop = popen(" grep stop_mcount System.map | awk '{print $1}' ", "r"); +- if (!file_stop) { +- fprintf(stderr, "get stop_mcount_loc error!"); +- pclose(file_start); +- return; +- } +- +- while (fgets(start_buff, sizeof(start_buff), file_start) != NULL) { +- len = strlen(start_buff); +- start_buff[len - 1] = '\0'; +- } +- *_start = strtoul(start_buff, NULL, 16); +- +- while (fgets(stop_buff, sizeof(stop_buff), file_stop) != NULL) { +- len = strlen(stop_buff); +- stop_buff[len - 1] = '\0'; +- } +- *_stop = strtoul(stop_buff, NULL, 16); +- +- pclose(file_start); +- pclose(file_stop); +-} +-#endif +-static int do_sort(Elf_Ehdr *ehdr, +- char const *const fname, +- table_sort_t custom_sort) +-{ +- int rc = -1; +- Elf_Shdr *shdr_start; +- Elf_Shdr *strtab_sec = NULL; +- Elf_Shdr *symtab_sec = NULL; +- Elf_Shdr *extab_sec = NULL; +- Elf_Shdr *string_sec; +- Elf_Sym *sym; +- const Elf_Sym *symtab; +- Elf32_Word *symtab_shndx = NULL; +- Elf_Sym *sort_needed_sym = NULL; +- Elf_Shdr *sort_needed_sec; +- uint32_t *sort_needed_loc; +- void *sym_start; +- void *sym_end; +- const char *secstrings; +- const char *strtab; +- char *extab_image; +- int sort_need_index; +- int symentsize; +- int shentsize; +- int idx; +- int i; +- unsigned int shnum; +- unsigned int shstrndx; +-#ifdef MCOUNT_SORT_ENABLED +- struct elf_mcount_loc mstruct = {0}; +- uint64_t _start_mcount_loc = 0; +- uint64_t _stop_mcount_loc = 0; +-#endif +-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +- unsigned int orc_ip_size = 0; +- unsigned int orc_size = 0; +- unsigned int orc_num_entries = 0; +-#endif +- +- shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); +- shentsize = ehdr_shentsize(ehdr); +- +- shstrndx = ehdr_shstrndx(ehdr); +- if (shstrndx == SHN_XINDEX) +- shstrndx = shdr_link(shdr_start); +- string_sec = get_index(shdr_start, shentsize, shstrndx); +- secstrings = (const char *)ehdr + shdr_offset(string_sec); +- +- shnum = ehdr_shnum(ehdr); +- if (shnum == SHN_UNDEF) +- shnum = shdr_size(shdr_start); +- +- for (i = 0; i < shnum; i++) { +- Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); +- +- idx = shdr_name(shdr); +- if (!strcmp(secstrings + idx, "__ex_table")) +- extab_sec = shdr; +- if (!strcmp(secstrings + idx, ".symtab")) +- symtab_sec = shdr; +- if (!strcmp(secstrings + idx, ".strtab")) +- strtab_sec = shdr; +- +- if (shdr_type(shdr) == SHT_SYMTAB_SHNDX) +- symtab_shndx = (Elf32_Word *)((const char *)ehdr + +- shdr_offset(shdr)); +- +-#ifdef MCOUNT_SORT_ENABLED +- /* locate the .init.data section in vmlinux */ +- if (!strcmp(secstrings + idx, ".init.data")) { +- get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc); +- mstruct.ehdr = ehdr; +- mstruct.init_data_sec = shdr; +- mstruct.start_mcount_loc = _start_mcount_loc; +- mstruct.stop_mcount_loc = _stop_mcount_loc; +- } +-#endif +- +-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +- /* locate the ORC unwind tables */ +- if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { +- orc_ip_size = shdr_size(shdr); +- g_orc_ip_table = (int *)((void *)ehdr + +- shdr_offset(shdr)); +- } +- if (!strcmp(secstrings + idx, ".orc_unwind")) { +- orc_size = shdr_size(shdr); +- g_orc_table = (struct orc_entry *)((void *)ehdr + +- shdr_offset(shdr)); +- } +-#endif +- } /* for loop */ +- +-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +- if (!g_orc_ip_table || !g_orc_table) { +- fprintf(stderr, +- "incomplete ORC unwind tables in file: %s\n", fname); +- goto out; +- } +- +- orc_num_entries = orc_ip_size / sizeof(int); +- if (orc_ip_size % sizeof(int) != 0 || +- orc_size % sizeof(struct orc_entry) != 0 || +- orc_num_entries != orc_size / sizeof(struct orc_entry)) { +- fprintf(stderr, +- "inconsistent ORC unwind table entries in file: %s\n", +- fname); +- goto out; +- } +- +- /* create thread to sort ORC unwind tables concurrently */ +- if (pthread_create(&orc_sort_thread, NULL, +- sort_orctable, &orc_ip_size)) { +- fprintf(stderr, +- "pthread_create orc_sort_thread failed '%s': %s\n", +- strerror(errno), fname); +- goto out; +- } +-#endif +- +-#ifdef MCOUNT_SORT_ENABLED +- if (!mstruct.init_data_sec || !_start_mcount_loc || !_stop_mcount_loc) { +- fprintf(stderr, +- "incomplete mcount's sort in file: %s\n", +- fname); +- goto out; +- } +- +- /* create thread to sort mcount_loc concurrently */ +- if (pthread_create(&mcount_sort_thread, NULL, &sort_mcount_loc, &mstruct)) { +- fprintf(stderr, +- "pthread_create mcount_sort_thread failed '%s': %s\n", +- strerror(errno), fname); +- goto out; +- } +-#endif +- if (!extab_sec) { +- fprintf(stderr, "no __ex_table in file: %s\n", fname); +- goto out; +- } +- +- if (!symtab_sec) { +- fprintf(stderr, "no .symtab in file: %s\n", fname); +- goto out; +- } +- +- if (!strtab_sec) { +- fprintf(stderr, "no .strtab in file: %s\n", fname); +- goto out; +- } +- +- extab_image = (void *)ehdr + shdr_offset(extab_sec); +- strtab = (const char *)ehdr + shdr_offset(strtab_sec); +- symtab = (const Elf_Sym *)((const char *)ehdr + shdr_offset(symtab_sec)); +- +- if (custom_sort) { +- custom_sort(extab_image, shdr_size(extab_sec)); +- } else { +- int num_entries = shdr_size(extab_sec) / extable_ent_size; +- qsort(extab_image, num_entries, +- extable_ent_size, compare_extable); +- } +- +- /* find the flag main_extable_sort_needed */ +- sym_start = (void *)ehdr + shdr_offset(symtab_sec); +- sym_end = sym_start + shdr_size(symtab_sec); +- symentsize = shdr_entsize(symtab_sec); +- +- for (sym = sym_start; (void *)sym + symentsize < sym_end; +- sym = (void *)sym + symentsize) { +- if (sym_type(sym) != STT_OBJECT) +- continue; +- if (!strcmp(strtab + sym_name(sym), +- "main_extable_sort_needed")) { +- sort_needed_sym = sym; +- break; +- } +- } +- +- if (!sort_needed_sym) { +- fprintf(stderr, +- "no main_extable_sort_needed symbol in file: %s\n", +- fname); +- goto out; +- } +- +- sort_need_index = get_secindex(sym_shndx(sym), +- ((void *)sort_needed_sym - (void *)symtab) / symentsize, +- symtab_shndx); +- sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index); +- sort_needed_loc = (void *)ehdr + +- shdr_offset(sort_needed_sec) + +- sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec); +- +- /* extable has been sorted, clear the flag */ +- w(0, sort_needed_loc); +- rc = 0; +- +-out: +-#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +- if (orc_sort_thread) { +- void *retval = NULL; +- /* wait for ORC tables sort done */ +- rc = pthread_join(orc_sort_thread, &retval); +- if (rc) { +- fprintf(stderr, +- "pthread_join failed '%s': %s\n", +- strerror(errno), fname); +- } else if (retval) { +- rc = -1; +- fprintf(stderr, +- "failed to sort ORC tables '%s': %s\n", +- (char *)retval, fname); +- } +- } +-#endif +- +-#ifdef MCOUNT_SORT_ENABLED +- if (mcount_sort_thread) { +- void *retval = NULL; +- /* wait for mcount sort done */ +- rc = pthread_join(mcount_sort_thread, &retval); +- if (rc) { +- fprintf(stderr, +- "pthread_join failed '%s': %s\n", +- strerror(errno), fname); +- } else if (retval) { +- rc = -1; +- fprintf(stderr, +- "failed to sort mcount '%s': %s\n", +- (char *)retval, fname); +- } +- } +-#endif +- return rc; +-} diff --git a/queue-6.6/scripts-sorttable-remove-unneeded-elf_rel.patch b/queue-6.6/scripts-sorttable-remove-unneeded-elf_rel.patch new file mode 100644 index 0000000000..dd5719ba12 --- /dev/null +++ b/queue-6.6/scripts-sorttable-remove-unneeded-elf_rel.patch @@ -0,0 +1,115 @@ +From stable+bounces-267239-greg=kroah.com@vger.kernel.org Thu Jun 18 21:40:45 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:41 -0400 +Subject: scripts/sorttable: Remove unneeded Elf_Rel +To: +Cc: , , , , , +Message-ID: + +From: Steven Rostedt + +[ Upstream commit 6f2c2f93a190467cebd6ebd03feb49514fead5ca ] + +The code had references to initialize the Elf_Rel relocation tables, but +it was never used. Remove it. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162344.515342233@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.h | 23 ++--------------------- + 1 file changed, 2 insertions(+), 21 deletions(-) + +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -26,7 +26,6 @@ + #undef Elf_Addr + #undef Elf_Ehdr + #undef Elf_Shdr +-#undef Elf_Rel + #undef Elf_Sym + #undef ELF_ST_TYPE + #undef uint_t +@@ -42,7 +41,6 @@ + # define Elf_Addr Elf64_Addr + # define Elf_Ehdr Elf64_Ehdr + # define Elf_Shdr Elf64_Shdr +-# define Elf_Rel Elf64_Rel + # define Elf_Sym Elf64_Sym + # define ELF_ST_TYPE ELF64_ST_TYPE + # define uint_t uint64_t +@@ -57,7 +55,6 @@ + # define Elf_Addr Elf32_Addr + # define Elf_Ehdr Elf32_Ehdr + # define Elf_Shdr Elf32_Shdr +-# define Elf_Rel Elf32_Rel + # define Elf_Sym Elf32_Sym + # define ELF_ST_TYPE ELF32_ST_TYPE + # define uint_t uint32_t +@@ -248,14 +245,10 @@ static int do_sort(Elf_Ehdr *ehdr, + Elf32_Word *symtab_shndx = NULL; + Elf_Sym *sort_needed_sym = NULL; + Elf_Shdr *sort_needed_sec; +- Elf_Rel *relocs = NULL; +- int relocs_size = 0; + uint32_t *sort_needed_loc; + const char *secstrings; + const char *strtab; + char *extab_image; +- int extab_index = 0; +- int i; + int idx; + unsigned int shnum; + unsigned int shstrndx; +@@ -279,23 +272,15 @@ static int do_sort(Elf_Ehdr *ehdr, + if (shnum == SHN_UNDEF) + shnum = _r(&shdr[0].sh_size); + +- for (i = 0, s = shdr; s < shdr + shnum; i++, s++) { ++ for (s = shdr; s < shdr + shnum; s++) { + idx = r(&s->sh_name); +- if (!strcmp(secstrings + idx, "__ex_table")) { ++ if (!strcmp(secstrings + idx, "__ex_table")) + extab_sec = s; +- extab_index = i; +- } + if (!strcmp(secstrings + idx, ".symtab")) + symtab_sec = s; + if (!strcmp(secstrings + idx, ".strtab")) + strtab_sec = s; + +- if ((r(&s->sh_type) == SHT_REL || +- r(&s->sh_type) == SHT_RELA) && +- r(&s->sh_info) == extab_index) { +- relocs = (void *)ehdr + _r(&s->sh_offset); +- relocs_size = _r(&s->sh_size); +- } + if (r(&s->sh_type) == SHT_SYMTAB_SHNDX) + symtab_shndx = (Elf32_Word *)((const char *)ehdr + + _r(&s->sh_offset)); +@@ -397,10 +382,6 @@ static int do_sort(Elf_Ehdr *ehdr, + extable_ent_size, compare_extable); + } + +- /* If there were relocations, we no longer need them. */ +- if (relocs) +- memset(relocs, 0, relocs_size); +- + /* find the flag main_extable_sort_needed */ + for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset); + sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); diff --git a/queue-6.6/scripts-sorttable-remove-unused-macro-defines.patch b/queue-6.6/scripts-sorttable-remove-unused-macro-defines.patch new file mode 100644 index 0000000000..61231bae1c --- /dev/null +++ b/queue-6.6/scripts-sorttable-remove-unused-macro-defines.patch @@ -0,0 +1,101 @@ +From stable+bounces-267237-greg=kroah.com@vger.kernel.org Thu Jun 18 21:40:37 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:39 -0400 +Subject: scripts/sorttable: Remove unused macro defines +To: +Cc: , , , , , +Message-ID: <6f62166c4fc68f959529f0ec0d9877ec52564762.1781814090.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 28b24394c6e9a3166fcb4480cba054562526657c ] + +The code of sorttable.h was copied from the recordmcount.h which defined +a bunch of Elf MACROs so that they could be used between 32bit and 64bit +functions. But there's several MACROs that sorttable.h does not use but +was copied over. Remove them to clean up the code. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162344.128870118@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.h | 27 --------------------------- + 1 file changed, 27 deletions(-) + +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -27,19 +27,10 @@ + #undef Elf_Ehdr + #undef Elf_Shdr + #undef Elf_Rel +-#undef Elf_Rela + #undef Elf_Sym +-#undef ELF_R_SYM +-#undef Elf_r_sym +-#undef ELF_R_INFO +-#undef Elf_r_info +-#undef ELF_ST_BIND + #undef ELF_ST_TYPE +-#undef fn_ELF_R_SYM +-#undef fn_ELF_R_INFO + #undef uint_t + #undef _r +-#undef _w + + #ifdef SORTTABLE_64 + # define extable_ent_size 16 +@@ -52,19 +43,10 @@ + # define Elf_Ehdr Elf64_Ehdr + # define Elf_Shdr Elf64_Shdr + # define Elf_Rel Elf64_Rel +-# define Elf_Rela Elf64_Rela + # define Elf_Sym Elf64_Sym +-# define ELF_R_SYM ELF64_R_SYM +-# define Elf_r_sym Elf64_r_sym +-# define ELF_R_INFO ELF64_R_INFO +-# define Elf_r_info Elf64_r_info +-# define ELF_ST_BIND ELF64_ST_BIND + # define ELF_ST_TYPE ELF64_ST_TYPE +-# define fn_ELF_R_SYM fn_ELF64_R_SYM +-# define fn_ELF_R_INFO fn_ELF64_R_INFO + # define uint_t uint64_t + # define _r r8 +-# define _w w8 + #else + # define extable_ent_size 8 + # define compare_extable compare_extable_32 +@@ -76,19 +58,10 @@ + # define Elf_Ehdr Elf32_Ehdr + # define Elf_Shdr Elf32_Shdr + # define Elf_Rel Elf32_Rel +-# define Elf_Rela Elf32_Rela + # define Elf_Sym Elf32_Sym +-# define ELF_R_SYM ELF32_R_SYM +-# define Elf_r_sym Elf32_r_sym +-# define ELF_R_INFO ELF32_R_INFO +-# define Elf_r_info Elf32_r_info +-# define ELF_ST_BIND ELF32_ST_BIND + # define ELF_ST_TYPE ELF32_ST_TYPE +-# define fn_ELF_R_SYM fn_ELF32_R_SYM +-# define fn_ELF_R_INFO fn_ELF32_R_INFO + # define uint_t uint32_t + # define _r r +-# define _w w + #endif + + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) diff --git a/queue-6.6/scripts-sorttable-remove-unused-write-functions.patch b/queue-6.6/scripts-sorttable-remove-unused-write-functions.patch new file mode 100644 index 0000000000..f021456e9c --- /dev/null +++ b/queue-6.6/scripts-sorttable-remove-unused-write-functions.patch @@ -0,0 +1,99 @@ +From stable+bounces-267238-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:23 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:40 -0400 +Subject: scripts/sorttable: Remove unused write functions +To: +Cc: , , , , , +Message-ID: <5c94be5c724fa489a859761ff8adb42f5d9dec4d.1781814092.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 4f48a28b37d594dab38092514a42ae9f4b781553 ] + +The code of sorttable.h was copied from the recordmcount.h which defined +various write functions for different sizes (2, 4, 8 byte lengths). But +sorttable only uses the 4 byte writes. Remove the extra versions as they +are not used. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162344.314385504@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 26 -------------------------- + 1 file changed, 26 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -68,8 +68,6 @@ 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 (*w2)(uint16_t, uint16_t *); +-static void (*w8)(uint64_t, uint64_t *); + typedef void (*table_sort_t)(char *, int); + + /* +@@ -146,31 +144,11 @@ static void wbe(uint32_t val, uint32_t * + put_unaligned_be32(val, x); + } + +-static void w2be(uint16_t val, uint16_t *x) +-{ +- put_unaligned_be16(val, x); +-} +- +-static void w8be(uint64_t val, uint64_t *x) +-{ +- put_unaligned_be64(val, x); +-} +- + static void wle(uint32_t val, uint32_t *x) + { + put_unaligned_le32(val, x); + } + +-static void w2le(uint16_t val, uint16_t *x) +-{ +- put_unaligned_le16(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 +@@ -277,16 +255,12 @@ static int do_file(char const *const fna + r2 = r2le; + r8 = r8le; + w = wle; +- w2 = w2le; +- w8 = w8le; + break; + case ELFDATA2MSB: + r = rbe; + r2 = r2be; + r8 = r8be; + w = wbe; +- w2 = w2be; +- w8 = w8be; + break; + default: + fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", diff --git a/queue-6.6/scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch b/queue-6.6/scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch new file mode 100644 index 0000000000..149f51417b --- /dev/null +++ b/queue-6.6/scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch @@ -0,0 +1,253 @@ +From prvs=262951c835=andrey.grodzovsky@crowdstrike.com Thu Jun 18 21:39:21 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:45 -0400 +Subject: scripts/sorttable: Replace Elf_Shdr Macro with a union +To: +Cc: , , , , , +Message-ID: <52839599d3d153450ee462499e049f0fdaf867c2.1781814106.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 545f6cf8f4c9a268e0bab2637f1d279679befdbf ] + +In order to remove the double #include of sorttable.h for 64 and 32 bit +to create duplicate functions for both, replace the Elf_Shdr macro with a +union that defines both Elf64_Shdr and Elf32_Shdr, with field e64 for the +64bit version, and e32 for the 32bit version. + +It can then use the macro etype to get the proper value. + +This will eventually be replaced with just single functions that can +handle both 32bit and 64bit ELF parsing. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162345.339462681@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 10 +++++++ + scripts/sorttable.h | 74 ++++++++++++++++++++++++++++------------------------ + 2 files changed, 51 insertions(+), 33 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -69,6 +69,11 @@ typedef union { + Elf64_Ehdr e64; + } Elf_Ehdr; + ++typedef union { ++ Elf32_Shdr e32; ++ Elf64_Shdr e64; ++} Elf_Shdr; ++ + static uint32_t (*r)(const uint32_t *); + static uint16_t (*r2)(const uint16_t *); + static uint64_t (*r8)(const uint64_t *); +@@ -198,6 +203,11 @@ static int compare_extable_64(const void + return av > bv; + } + ++static inline void *get_index(void *start, int entsize, int index) ++{ ++ return start + (entsize * index); ++} ++ + /* 32 bit and 64 bit are very similar */ + #include "sorttable.h" + #define SORTTABLE_64 +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -23,7 +23,6 @@ + #undef sort_mcount_loc + #undef elf_mcount_loc + #undef do_sort +-#undef Elf_Shdr + #undef Elf_Sym + #undef ELF_ST_TYPE + #undef uint_t +@@ -37,7 +36,6 @@ + # define sort_mcount_loc sort_mcount_loc_64 + # define elf_mcount_loc elf_mcount_loc_64 + # define do_sort do_sort_64 +-# define Elf_Shdr Elf64_Shdr + # define Elf_Sym Elf64_Sym + # define ELF_ST_TYPE ELF64_ST_TYPE + # define uint_t uint64_t +@@ -50,7 +48,6 @@ + # define sort_mcount_loc sort_mcount_loc_32 + # define elf_mcount_loc elf_mcount_loc_32 + # define do_sort do_sort_32 +-# define Elf_Shdr Elf32_Shdr + # define Elf_Sym Elf32_Sym + # define ELF_ST_TYPE ELF32_ST_TYPE + # define uint_t uint32_t +@@ -171,8 +168,8 @@ struct elf_mcount_loc { + static void *sort_mcount_loc(void *arg) + { + struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg; +- uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->sh_addr) +- + _r(&(emloc->init_data_sec)->sh_offset); ++ uint_t offset = emloc->start_mcount_loc - _r(&(emloc->init_data_sec)->etype.sh_addr) ++ + _r(&(emloc->init_data_sec)->etype.sh_offset); + uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; + unsigned char *start_loc = (void *)emloc->ehdr + offset; + +@@ -222,10 +219,11 @@ static int do_sort(Elf_Ehdr *ehdr, + table_sort_t custom_sort) + { + int rc = -1; +- Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff)); ++ Elf_Shdr *shdr_start; + Elf_Shdr *strtab_sec = NULL; + Elf_Shdr *symtab_sec = NULL; + Elf_Shdr *extab_sec = NULL; ++ Elf_Shdr *string_sec; + Elf_Sym *sym; + const Elf_Sym *symtab; + Elf32_Word *symtab_shndx = NULL; +@@ -235,7 +233,10 @@ static int do_sort(Elf_Ehdr *ehdr, + const char *secstrings; + const char *strtab; + char *extab_image; ++ int sort_need_index; ++ int shentsize; + int idx; ++ int i; + unsigned int shnum; + unsigned int shstrndx; + #ifdef MCOUNT_SORT_ENABLED +@@ -249,34 +250,40 @@ static int do_sort(Elf_Ehdr *ehdr, + unsigned int orc_num_entries = 0; + #endif + ++ shdr_start = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->etype.e_shoff)); ++ shentsize = r2(&ehdr->etype.e_shentsize); ++ + shstrndx = r2(&ehdr->etype.e_shstrndx); + if (shstrndx == SHN_XINDEX) +- shstrndx = r(&shdr[0].sh_link); +- secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset); ++ shstrndx = r(&shdr_start->etype.sh_link); ++ string_sec = get_index(shdr_start, shentsize, shstrndx); ++ secstrings = (const char *)ehdr + _r(&string_sec->etype.sh_offset); + + shnum = r2(&ehdr->etype.e_shnum); + if (shnum == SHN_UNDEF) +- shnum = _r(&shdr[0].sh_size); ++ shnum = _r(&shdr_start->etype.sh_size); ++ ++ for (i = 0; i < shnum; i++) { ++ Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); + +- for (s = shdr; s < shdr + shnum; s++) { +- idx = r(&s->sh_name); ++ idx = r(&shdr->etype.sh_name); + if (!strcmp(secstrings + idx, "__ex_table")) +- extab_sec = s; ++ extab_sec = shdr; + if (!strcmp(secstrings + idx, ".symtab")) +- symtab_sec = s; ++ symtab_sec = shdr; + if (!strcmp(secstrings + idx, ".strtab")) +- strtab_sec = s; ++ strtab_sec = shdr; + +- if (r(&s->sh_type) == SHT_SYMTAB_SHNDX) ++ if (r(&shdr->etype.sh_type) == SHT_SYMTAB_SHNDX) + symtab_shndx = (Elf32_Word *)((const char *)ehdr + +- _r(&s->sh_offset)); ++ _r(&shdr->etype.sh_offset)); + + #ifdef MCOUNT_SORT_ENABLED + /* locate the .init.data section in vmlinux */ + if (!strcmp(secstrings + idx, ".init.data")) { + get_mcount_loc(&_start_mcount_loc, &_stop_mcount_loc); + mstruct.ehdr = ehdr; +- mstruct.init_data_sec = s; ++ mstruct.init_data_sec = shdr; + mstruct.start_mcount_loc = _start_mcount_loc; + mstruct.stop_mcount_loc = _stop_mcount_loc; + } +@@ -285,14 +292,14 @@ static int do_sort(Elf_Ehdr *ehdr, + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + /* locate the ORC unwind tables */ + if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { +- orc_ip_size = _r(&s->sh_size); ++ orc_ip_size = _r(&shdr->etype.sh_size); + g_orc_ip_table = (int *)((void *)ehdr + +- _r(&s->sh_offset)); ++ _r(&shdr->etype.sh_offset)); + } + if (!strcmp(secstrings + idx, ".orc_unwind")) { +- orc_size = _r(&s->sh_size); ++ orc_size = _r(&shdr->etype.sh_size); + g_orc_table = (struct orc_entry *)((void *)ehdr + +- _r(&s->sh_offset)); ++ _r(&shdr->etype.sh_offset)); + } + #endif + } /* for loop */ +@@ -355,22 +362,22 @@ static int do_sort(Elf_Ehdr *ehdr, + goto out; + } + +- extab_image = (void *)ehdr + _r(&extab_sec->sh_offset); +- strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset); ++ extab_image = (void *)ehdr + _r(&extab_sec->etype.sh_offset); ++ strtab = (const char *)ehdr + _r(&strtab_sec->etype.sh_offset); + symtab = (const Elf_Sym *)((const char *)ehdr + +- _r(&symtab_sec->sh_offset)); ++ _r(&symtab_sec->etype.sh_offset)); + + if (custom_sort) { +- custom_sort(extab_image, _r(&extab_sec->sh_size)); ++ custom_sort(extab_image, _r(&extab_sec->etype.sh_size)); + } else { +- int num_entries = _r(&extab_sec->sh_size) / extable_ent_size; ++ int num_entries = _r(&extab_sec->etype.sh_size) / extable_ent_size; + qsort(extab_image, num_entries, + extable_ent_size, compare_extable); + } + + /* find the flag main_extable_sort_needed */ +- for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset); +- sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); ++ for (sym = (void *)ehdr + _r(&symtab_sec->etype.sh_offset); ++ sym < sym + _r(&symtab_sec->etype.sh_size) / sizeof(Elf_Sym); + sym++) { + if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) + continue; +@@ -388,13 +395,14 @@ static int do_sort(Elf_Ehdr *ehdr, + goto out; + } + +- sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx), +- sort_needed_sym - symtab, +- symtab_shndx)]; ++ sort_need_index = get_secindex(r2(&sym->st_shndx), ++ sort_needed_sym - symtab, ++ symtab_shndx); ++ sort_needed_sec = get_index(shdr_start, shentsize, sort_need_index); + sort_needed_loc = (void *)ehdr + +- _r(&sort_needed_sec->sh_offset) + ++ _r(&sort_needed_sec->etype.sh_offset) + + _r(&sort_needed_sym->st_value) - +- _r(&sort_needed_sec->sh_addr); ++ _r(&sort_needed_sec->etype.sh_addr); + + /* extable has been sorted, clear the flag */ + w(0, sort_needed_loc); diff --git a/queue-6.6/scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch b/queue-6.6/scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch new file mode 100644 index 0000000000..bb96d0cba9 --- /dev/null +++ b/queue-6.6/scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch @@ -0,0 +1,323 @@ +From stable+bounces-267251-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:41 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:53 -0400 +Subject: scripts/sorttable: Use a structure of function pointers for elf helpers +To: +Cc: , , , , , +Message-ID: <377ded38dbd2eae778204e8a1c42e24d9814da8c.1781814131.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 1e5f6771c247b28135307058d2cfe3b0153733dc ] + +Instead of having a series of function pointers that gets assigned to the +Elf64 or Elf32 versions, put them all into a single structure and use +that. Add the helper function that chooses the structure into the macros +that build the different versions of the elf functions. + +Link: https://lore.kernel.org/all/CAHk-=wiafEyX7UgOeZgvd6fvuByE5WXUPh9599kwOc_d-pdeug@mail.gmail.com/ + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Stephen Rothwell +Link: https://lore.kernel.org/20250110075459.13d4b94c@gandalf.local.home +Suggested-by: Linus Torvalds +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 175 +++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 118 insertions(+), 57 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -85,6 +85,25 @@ static uint64_t (*r8)(const uint64_t *); + static void (*w)(uint32_t, uint32_t *); + typedef void (*table_sort_t)(char *, int); + ++static struct elf_funcs { ++ int (*compare_extable)(const void *a, const void *b); ++ uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr); ++ uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr); ++ uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr); ++ uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr); ++ uint64_t (*shdr_addr)(Elf_Shdr *shdr); ++ uint64_t (*shdr_offset)(Elf_Shdr *shdr); ++ uint64_t (*shdr_size)(Elf_Shdr *shdr); ++ uint64_t (*shdr_entsize)(Elf_Shdr *shdr); ++ uint32_t (*shdr_link)(Elf_Shdr *shdr); ++ uint32_t (*shdr_name)(Elf_Shdr *shdr); ++ uint32_t (*shdr_type)(Elf_Shdr *shdr); ++ uint8_t (*sym_type)(Elf_Sym *sym); ++ uint32_t (*sym_name)(Elf_Sym *sym); ++ uint64_t (*sym_value)(Elf_Sym *sym); ++ uint16_t (*sym_shndx)(Elf_Sym *sym); ++} e; ++ + static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) + { + return r8(&ehdr->e64.e_shoff); +@@ -95,6 +114,11 @@ static uint64_t ehdr32_shoff(Elf_Ehdr *e + return r(&ehdr->e32.e_shoff); + } + ++static uint64_t ehdr_shoff(Elf_Ehdr *ehdr) ++{ ++ return e.ehdr_shoff(ehdr); ++} ++ + #define EHDR_HALF(fn_name) \ + static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \ + { \ +@@ -104,6 +128,11 @@ static uint16_t ehdr64_##fn_name(Elf_Ehd + static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \ + { \ + return r2(&ehdr->e32.e_##fn_name); \ ++} \ ++ \ ++static uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \ ++{ \ ++ return e.ehdr_##fn_name(ehdr); \ + } + + EHDR_HALF(shentsize) +@@ -119,6 +148,11 @@ static uint32_t shdr64_##fn_name(Elf_Shd + static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ + { \ + return r(&shdr->e32.sh_##fn_name); \ ++} \ ++ \ ++static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return e.shdr_##fn_name(shdr); \ + } + + #define SHDR_ADDR(fn_name) \ +@@ -130,6 +164,11 @@ static uint64_t shdr64_##fn_name(Elf_Shd + static uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \ + { \ + return r(&shdr->e32.sh_##fn_name); \ ++} \ ++ \ ++static uint64_t shdr_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return e.shdr_##fn_name(shdr); \ + } + + #define SHDR_WORD(fn_name) \ +@@ -141,6 +180,10 @@ static uint32_t shdr64_##fn_name(Elf_Shd + static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \ + { \ + return r(&shdr->e32.sh_##fn_name); \ ++} \ ++static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \ ++{ \ ++ return e.shdr_##fn_name(shdr); \ + } + + SHDR_ADDR(addr) +@@ -161,6 +204,11 @@ static uint64_t sym64_##fn_name(Elf_Sym + static uint64_t sym32_##fn_name(Elf_Sym *sym) \ + { \ + return r(&sym->e32.st_##fn_name); \ ++} \ ++ \ ++static uint64_t sym_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return e.sym_##fn_name(sym); \ + } + + #define SYM_WORD(fn_name) \ +@@ -172,6 +220,11 @@ static uint32_t sym64_##fn_name(Elf_Sym + static uint32_t sym32_##fn_name(Elf_Sym *sym) \ + { \ + return r(&sym->e32.st_##fn_name); \ ++} \ ++ \ ++static uint32_t sym_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return e.sym_##fn_name(sym); \ + } + + #define SYM_HALF(fn_name) \ +@@ -183,6 +236,11 @@ static uint16_t sym64_##fn_name(Elf_Sym + static uint16_t sym32_##fn_name(Elf_Sym *sym) \ + { \ + return r2(&sym->e32.st_##fn_name); \ ++} \ ++ \ ++static uint16_t sym_##fn_name(Elf_Sym *sym) \ ++{ \ ++ return e.sym_##fn_name(sym); \ + } + + static uint8_t sym64_type(Elf_Sym *sym) +@@ -195,6 +253,11 @@ static uint8_t sym32_type(Elf_Sym *sym) + return ELF32_ST_TYPE(sym->e32.st_info); + } + ++static uint8_t sym_type(Elf_Sym *sym) ++{ ++ return e.sym_type(sym); ++} ++ + SYM_ADDR(value) + SYM_WORD(name) + SYM_HALF(shndx) +@@ -322,29 +385,16 @@ static int compare_extable_64(const void + return av > bv; + } + ++static int compare_extable(const void *a, const void *b) ++{ ++ return e.compare_extable(a, b); ++} ++ + static inline void *get_index(void *start, int entsize, int index) + { + return start + (entsize * index); + } + +- +-static int (*compare_extable)(const void *a, const void *b); +-static uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr); +-static uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr); +-static uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr); +-static uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr); +-static uint64_t (*shdr_addr)(Elf_Shdr *shdr); +-static uint64_t (*shdr_offset)(Elf_Shdr *shdr); +-static uint64_t (*shdr_size)(Elf_Shdr *shdr); +-static uint64_t (*shdr_entsize)(Elf_Shdr *shdr); +-static uint32_t (*shdr_link)(Elf_Shdr *shdr); +-static uint32_t (*shdr_name)(Elf_Shdr *shdr); +-static uint32_t (*shdr_type)(Elf_Shdr *shdr); +-static uint8_t (*sym_type)(Elf_Sym *sym); +-static uint32_t (*sym_name)(Elf_Sym *sym); +-static uint64_t (*sym_value)(Elf_Sym *sym); +-static uint16_t (*sym_shndx)(Elf_Sym *sym); +- + static int extable_ent_size; + static int long_size; + +@@ -864,7 +914,30 @@ static int do_file(char const *const fna + } + + switch (ehdr->e32.e_ident[EI_CLASS]) { +- case ELFCLASS32: ++ case ELFCLASS32: { ++ struct elf_funcs efuncs = { ++ .compare_extable = compare_extable_32, ++ .ehdr_shoff = ehdr32_shoff, ++ .ehdr_shentsize = ehdr32_shentsize, ++ .ehdr_shstrndx = ehdr32_shstrndx, ++ .ehdr_shnum = ehdr32_shnum, ++ .shdr_addr = shdr32_addr, ++ .shdr_offset = shdr32_offset, ++ .shdr_link = shdr32_link, ++ .shdr_size = shdr32_size, ++ .shdr_name = shdr32_name, ++ .shdr_type = shdr32_type, ++ .shdr_entsize = shdr32_entsize, ++ .sym_type = sym32_type, ++ .sym_name = sym32_name, ++ .sym_value = sym32_value, ++ .sym_shndx = sym32_shndx, ++ }; ++ ++ e = efuncs; ++ long_size = 4; ++ extable_ent_size = 8; ++ + if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) || + r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) { + fprintf(stderr, +@@ -872,26 +945,32 @@ static int do_file(char const *const fna + return -1; + } + +- compare_extable = compare_extable_32; +- ehdr_shoff = ehdr32_shoff; +- ehdr_shentsize = ehdr32_shentsize; +- ehdr_shstrndx = ehdr32_shstrndx; +- ehdr_shnum = ehdr32_shnum; +- shdr_addr = shdr32_addr; +- shdr_offset = shdr32_offset; +- shdr_link = shdr32_link; +- shdr_size = shdr32_size; +- shdr_name = shdr32_name; +- shdr_type = shdr32_type; +- shdr_entsize = shdr32_entsize; +- sym_type = sym32_type; +- sym_name = sym32_name; +- sym_value = sym32_value; +- sym_shndx = sym32_shndx; +- long_size = 4; +- extable_ent_size = 8; ++ } + break; +- case ELFCLASS64: ++ case ELFCLASS64: { ++ struct elf_funcs efuncs = { ++ .compare_extable = compare_extable_64, ++ .ehdr_shoff = ehdr64_shoff, ++ .ehdr_shentsize = ehdr64_shentsize, ++ .ehdr_shstrndx = ehdr64_shstrndx, ++ .ehdr_shnum = ehdr64_shnum, ++ .shdr_addr = shdr64_addr, ++ .shdr_offset = shdr64_offset, ++ .shdr_link = shdr64_link, ++ .shdr_size = shdr64_size, ++ .shdr_name = shdr64_name, ++ .shdr_type = shdr64_type, ++ .shdr_entsize = shdr64_entsize, ++ .sym_type = sym64_type, ++ .sym_name = sym64_name, ++ .sym_value = sym64_value, ++ .sym_shndx = sym64_shndx, ++ }; ++ ++ e = efuncs; ++ long_size = 8; ++ extable_ent_size = 16; ++ + if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) || + r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) { + fprintf(stderr, +@@ -900,25 +979,7 @@ static int do_file(char const *const fna + return -1; + } + +- compare_extable = compare_extable_64; +- ehdr_shoff = ehdr64_shoff; +- ehdr_shentsize = ehdr64_shentsize; +- ehdr_shstrndx = ehdr64_shstrndx; +- ehdr_shnum = ehdr64_shnum; +- shdr_addr = shdr64_addr; +- shdr_offset = shdr64_offset; +- shdr_link = shdr64_link; +- shdr_size = shdr64_size; +- shdr_name = shdr64_name; +- shdr_type = shdr64_type; +- shdr_entsize = shdr64_entsize; +- sym_type = sym64_type; +- sym_name = sym64_name; +- sym_value = sym64_value; +- sym_shndx = sym64_shndx; +- long_size = 8; +- extable_ent_size = 16; +- ++ } + break; + default: + fprintf(stderr, "unrecognized ELF class %d %s\n", diff --git a/queue-6.6/scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch b/queue-6.6/scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch new file mode 100644 index 0000000000..ff5760065f --- /dev/null +++ b/queue-6.6/scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch @@ -0,0 +1,63 @@ +From stable+bounces-267261-greg=kroah.com@vger.kernel.org Thu Jun 18 21:40:06 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:39:03 -0400 +Subject: scripts/sorttable: Use normal sort if theres no relocs in the mcount section +To: +Cc: , , , , , +Message-ID: <5daea8fc47fe65aa9f94a6e7934be6b635df9c6a.1781814162.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 46514b3c2c17c67cefe84b0c1a59e0aaf6093131 ] + +When ARM 64 is compiled with gcc, the mcount_loc section will be filled +with zeros and the addresses will be located in the Elf_Rela sections. To +sort the mcount_loc section, the addresses from the Elf_Rela need to be +placed into an array and that is sorted. + +But when ARM 64 is compiled with clang, it does it the same way as other +architectures and leaves the addresses as is in the mcount_loc section. + +To handle both cases, ARM 64 will first try to sort the Elf_Rela section, +and if it doesn't find any functions, it will then fall back to the +sorting of the addresses in the mcount_loc section itself. + +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Masahiro Yamada +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Mark Brown +Link: https://lore.kernel.org/20250225182054.648398403@goodmis.org +Fixes: b3d09d06e052 ("arm64: scripts/sorttable: Implement sorting mcount_loc at boot for arm64") +Reported-by: "Arnd Bergmann" +Tested-by: Nathan Chancellor +Closes: https://lore.kernel.org/all/893cd8f1-8585-4d25-bf0f-4197bf872465@app.fastmail.com/ +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -827,9 +827,14 @@ static void *sort_mcount_loc(void *arg) + pthread_exit(m_err); + } + +- if (sort_reloc) ++ if (sort_reloc) { + count = fill_relocs(vals, size, ehdr, emloc->start_mcount_loc); +- else ++ /* gcc may use relocs to save the addresses, but clang does not. */ ++ if (!count) { ++ count = fill_addrs(vals, size, start_loc); ++ sort_reloc = 0; ++ } ++ } else + count = fill_addrs(vals, size, start_loc); + + if (count < 0) { diff --git a/queue-6.6/scripts-sorttable-use-uint64_t-for-mcount-sorting.patch b/queue-6.6/scripts-sorttable-use-uint64_t-for-mcount-sorting.patch new file mode 100644 index 0000000000..f8b60e9fba --- /dev/null +++ b/queue-6.6/scripts-sorttable-use-uint64_t-for-mcount-sorting.patch @@ -0,0 +1,137 @@ +From stable+bounces-267248-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:38 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:50 -0400 +Subject: scripts/sorttable: Use uint64_t for mcount sorting +To: +Cc: , , , , , +Message-ID: <2cf3a7cb8035a129abaa492eb4b7c88cedf05cf5.1781814124.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit 1b649e6ab8dc9188d82c64069493afe66ca0edad ] + +The mcount sorting defines uint_t to uint64_t on 64bit architectures and +uint32_t on 32bit architectures. It can work with just using uint64_t as +that will hold the values of both, and they are not used to point into the +ELF file. + +sizeof(uint_t) is used for defining the size of the mcount_loc section. +Instead of using a type, define long_size and use that instead. This will +allow the header code to be moved into the C file as generic functions and +not need to include sorttable.h twice, once for 64bit and once for 32bit. + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Link: https://lore.kernel.org/20250105162346.373528925@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + scripts/sorttable.h | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/scripts/sorttable.h ++++ b/scripts/sorttable.h +@@ -23,7 +23,6 @@ + #undef sort_mcount_loc + #undef elf_mcount_loc + #undef do_sort +-#undef uint_t + #undef ehdr_shoff + #undef ehdr_shentsize + #undef ehdr_shstrndx +@@ -39,6 +38,7 @@ + #undef sym_name + #undef sym_value + #undef sym_shndx ++#undef long_size + + #ifdef SORTTABLE_64 + # define extable_ent_size 16 +@@ -47,7 +47,6 @@ + # define sort_mcount_loc sort_mcount_loc_64 + # define elf_mcount_loc elf_mcount_loc_64 + # define do_sort do_sort_64 +-# define uint_t uint64_t + # define ehdr_shoff ehdr64_shoff + # define ehdr_shentsize ehdr64_shentsize + # define ehdr_shstrndx ehdr64_shstrndx +@@ -63,6 +62,7 @@ + # define sym_name sym64_name + # define sym_value sym64_value + # define sym_shndx sym64_shndx ++# define long_size 8 + #else + # define extable_ent_size 8 + # define compare_extable compare_extable_32 +@@ -70,7 +70,6 @@ + # define sort_mcount_loc sort_mcount_loc_32 + # define elf_mcount_loc elf_mcount_loc_32 + # define do_sort do_sort_32 +-# define uint_t uint32_t + # define ehdr_shoff ehdr32_shoff + # define ehdr_shentsize ehdr32_shentsize + # define ehdr_shstrndx ehdr32_shstrndx +@@ -86,6 +85,7 @@ + # define sym_name sym32_name + # define sym_value sym32_value + # define sym_shndx sym32_shndx ++# define long_size 4 + #endif + + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +@@ -193,25 +193,25 @@ pthread_t mcount_sort_thread; + struct elf_mcount_loc { + Elf_Ehdr *ehdr; + Elf_Shdr *init_data_sec; +- uint_t start_mcount_loc; +- uint_t stop_mcount_loc; ++ uint64_t start_mcount_loc; ++ uint64_t stop_mcount_loc; + }; + + /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */ + static void *sort_mcount_loc(void *arg) + { + struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg; +- uint_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec) ++ uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec) + + shdr_offset(emloc->init_data_sec); +- uint_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; ++ uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; + unsigned char *start_loc = (void *)emloc->ehdr + offset; + +- qsort(start_loc, count/sizeof(uint_t), sizeof(uint_t), compare_extable); ++ qsort(start_loc, count/long_size, long_size, compare_extable); + return NULL; + } + + /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */ +-static void get_mcount_loc(uint_t *_start, uint_t *_stop) ++static void get_mcount_loc(uint64_t *_start, uint64_t *_stop) + { + FILE *file_start, *file_stop; + char start_buff[20]; +@@ -277,8 +277,8 @@ static int do_sort(Elf_Ehdr *ehdr, + unsigned int shstrndx; + #ifdef MCOUNT_SORT_ENABLED + struct elf_mcount_loc mstruct = {0}; +- uint_t _start_mcount_loc = 0; +- uint_t _stop_mcount_loc = 0; ++ uint64_t _start_mcount_loc = 0; ++ uint64_t _stop_mcount_loc = 0; + #endif + #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + unsigned int orc_ip_size = 0; diff --git a/queue-6.6/scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch b/queue-6.6/scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch new file mode 100644 index 0000000000..5cff709580 --- /dev/null +++ b/queue-6.6/scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch @@ -0,0 +1,311 @@ +From stable+bounces-267255-greg=kroah.com@vger.kernel.org Thu Jun 18 21:39:43 2026 +From: Andrey Grodzovsky +Date: Thu, 18 Jun 2026 16:38:57 -0400 +Subject: scripts/sorttable: Zero out weak functions in mcount_loc table +To: +Cc: , , , , , +Message-ID: <8ebf43f280b1b912161dc2e17d7a34090b6c9ea0.1781814143.git.andrey.grodzovsky@crowdstrike.com> + +From: Steven Rostedt + +[ Upstream commit ef378c3b8233855497a414b9d67bf22592c928a4 ] + +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 + +Cc: bpf +Cc: Masami Hiramatsu +Cc: Mark Rutland +Cc: Mathieu Desnoyers +Cc: Andrew Morton +Cc: Peter Zijlstra +Cc: Linus Torvalds +Cc: Masahiro Yamada +Cc: Nathan Chancellor +Cc: Nicolas Schier +Cc: Zheng Yejian +Cc: Martin Kelly +Cc: Christophe Leroy +Cc: Josh Poimboeuf +Cc: Heiko Carstens +Cc: Catalin Marinas +Cc: Will Deacon +Cc: Vasily Gorbik +Cc: Alexander Gordeev +Link: https://lore.kernel.org/20250218200022.883095980@goodmis.org +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Andrey Grodzovsky +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ftrace.c | 6 +- + scripts/link-vmlinux.sh | 4 + + scripts/sorttable.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 134 insertions(+), 4 deletions(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -6525,6 +6525,7 @@ static int ftrace_process_locs(struct mo + unsigned long count; + unsigned long *p; + unsigned long addr; ++ unsigned long kaslr; + unsigned long flags = 0; /* Shut up gcc */ + int ret = -ENOMEM; + +@@ -6573,6 +6574,9 @@ static int ftrace_process_locs(struct mo + 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) { +@@ -6584,7 +6588,7 @@ static int ftrace_process_locs(struct mo + * object files to satisfy alignments. + * Skip any NULL pointers. + */ +- if (!addr) { ++ if (!addr || addr == kaslr) { + skipped++; + continue; + } +--- a/scripts/link-vmlinux.sh ++++ b/scripts/link-vmlinux.sh +@@ -198,13 +198,15 @@ mksysmap() + + sorttable() + { +- ${objtree}/scripts/sorttable ${1} ++ ${NM} -S ${1} > .tmp_vmlinux.nm-sort ++ ${objtree}/scripts/sorttable -s .tmp_vmlinux.nm-sort ${1} + } + + # Delete output files in case of error + cleanup() + { + rm -f .btf.* ++ rm -f .tmp_vmlinux.nm-sort + rm -f System.map + rm -f vmlinux + rm -f vmlinux.map +--- a/scripts/sorttable.c ++++ b/scripts/sorttable.c +@@ -580,6 +580,98 @@ static void rela_write_addend(Elf_Rela * + 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' && type != 'W') ++ 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_mc + 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; diff --git a/queue-6.6/series b/queue-6.6/series index 01731f0656..8bdc5bc8a8 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -41,3 +41,30 @@ rxrpc-fix-the-ack-parser-to-extract-the-sack-table-for-parsing.patch slimbus-qcom-ngd-ctrl-fix-up-platform_driver-registration.patch slimbus-qcom-ngd-ctrl-balance-pm_runtime-enablement-for-ngd.patch fuse-re-lock-request-before-replacing-page-cache-folio.patch +scripts-sorttable-remove-unused-macro-defines.patch +scripts-sorttable-remove-unused-write-functions.patch +scripts-sorttable-remove-unneeded-elf_rel.patch +scripts-sorttable-have-the-orc-code-use-the-_r-functions-to-read.patch +scripts-sorttable-make-compare_extable-into-two-functions.patch +scripts-sorttable-convert-elf_ehdr-to-union.patch +scripts-sorttable-replace-elf_shdr-macro-with-a-union.patch +scripts-sorttable-convert-elf_sym-macro-over-to-a-union.patch +scripts-sorttable-add-helper-functions-for-elf_ehdr.patch +scripts-sorttable-add-helper-functions-for-elf_shdr.patch +scripts-sorttable-add-helper-functions-for-elf_sym.patch +scripts-sorttable-use-uint64_t-for-mcount-sorting.patch +scripts-sorttable-move-code-from-sorttable.h-into-sorttable.c.patch +scripts-sorttable-get-start-stop_mcount_loc-from-elf-file-directly.patch +scripts-sorttable-use-a-structure-of-function-pointers-for-elf-helpers.patch +arm64-scripts-sorttable-implement-sorting-mcount_loc-at-boot-for-arm64.patch +scripts-sorttable-have-mcount-rela-sort-use-direct-values.patch +scripts-sorttable-always-use-an-array-for-the-mcount_loc-sorting.patch +scripts-sorttable-zero-out-weak-functions-in-mcount_loc-table.patch +ftrace-update-the-mcount_loc-check-of-skipped-entries.patch +ftrace-have-ftrace-pages-output-reflect-freed-pages.patch +ftrace-do-not-over-allocate-ftrace-memory.patch +ftrace-test-mcount_loc-addr-before-calling-ftrace_call_addr.patch +ftrace-check-against-is_kernel_text-instead-of-kaslr_offset.patch +scripts-sorttable-use-normal-sort-if-theres-no-relocs-in-the-mcount-section.patch +scripts-sorttable-allow-matches-to-functions-before-function-entry.patch +scripts-sorttable-fix-endianness-handling-in-build-time-mcount-sort.patch