linux-trace-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions
@ 2025-01-02 23:26 Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 01/16] scripts/sorttable: Remove unused macro defines Steven Rostedt
                   ` (16 more replies)
  0 siblings, 17 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

This series removes the place holder __ftrace_invalid_address___ from
the available_filter_functions file.

The first 13 patches clean up the scripts/sorttable.c code. It was
a copy from recordmcount.c which is very hard to maintain. That's
because it uses macro helpers and places the code in a header file
sorttable.h to handle both the 64 bit and 32 bit version of  the Elf
structures. It also has _r()/r()/r2() wrappers around accessing the
data which will read the 64 bit or 32 bit version of the data as well
as handle endianess. If the wrong wrapper is used, an invalid value
will result, and this has been a cause for bugs in the past. In fact
the new ORC code doesn't even use it. That's fine because ORC is only
for 64 bit x86 which is the default parsing.

Instead of having a bunch of macros defined and then include the code
twice from a header, the Elf structures are each wrapped in a union.
The union holds the 64 bit and 32 bit version of the needed structure.
To access the values, helper function pointers are used instead of
defining a function. For example, instead of having:

In sorttable.h:

 #undef Elf_Ehdr
 #undef Elf_Shdr

 #ifdef SORTTABLE_64
 # define Elf_Ehdr		Elf64_Ehdr
 # define Elf_Shdr		Elf64_Shdr
 [..]
 # define _r			r8
 #else
 # define Elf_Ehdr		Elf32_Ehdr
 # define Elf_Shdr		Elf32_Shdr
 [..]
 # define _r			r
 #endif

 [..]
 Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));

In sorttable.c:

 #include "sorttable.h"
 #define SORTTABLE_64
 #include "sorttable.h"

Using the Unions we have:

 typedef union {
	Elf32_Ehdr	e32;
	Elf64_Ehdr	e64;
 } Elf_Ehdr;

 typedef union {
	Elf32_Shdr	e32;
	Elf64_Shdr	e64;
 } Elf_Shdr;

 [..]

 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);
 }

 [..]
 static uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
 [..]

	switch (ehdr->e32.e_ident[EI_CLASS]) {
	case ELFCLASS32:
		[..]
		ehdr_shoff	= ehdr32_shoff;
		[..]
	case ELFCLASS65:
		[..]
		ehdr_shoff	= ehdr64_shoff;
		[..]

 shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));

The code may be a little more verbose, but the meat of the code is easier to
read, and the conversion functions live in the helper functions to make
it easier to have the fields read the proper way.

This makes the code easier to maintain, and for this purpose easier
to extend. Which is the last patch of the series.

The last 3 patches work to remove the weak functions from the mcount_loc
section.

The first of the 3 replaces the hack to get the __start_mcount_loc and
__stop_mcount_loc values from the symbol table. It replaces calling
popen() on a grep of System.map with looking at the actual symbol
values in the elf format.

The next patch adds the option "-s <file>" to sorttable.c. Now this code
is called by:

  ${NM} -S vmlinux > .tmp_vmlinux.nm-sort
  ${objtree}/scripts/sorttable -s .tmp_vmlinux.nm-sort ${1}

Where the file created by "nm -S" is read, recording the address
and the associated sizes of each function. It then is sorted, and
before sorting the mcount_loc table, it is scanned to make sure
all symbols in the mcounc_loc are within the boundaries of the functions
defined by nm. If they are not, they are zeroed out, as they are most
likely weak functions (I don't know what else they would be).

The last patch adds a ftrace_mcount_skip initdata variable that is
updated by sorttable.c to tell ftrace to skip over the first entries
in the mcount_loc table as they are invalid.

Before:
    
 ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l
 556

After:

 ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l
 0

Ideally, I would have moved the __start_mcount_loc to not have to
modify the kernel, but that would require a bit more work in the
architecture dependent code, as it requires reading the Elf_Rel*
entries.

This is also independent on fixing kallsyms to be able to know the real
size of functions instead of just using the value that goes to the
next function. One solution is to add place holders for weak functions.
But this doesn't help the mcount_loc issue as these entries need to
be removed at boot up and searching kallsyms will have an non-negligible
overhead.

Changes since v1: https://lore.kernel.org/all/20250102185845.928488650@goodmis.org/

- Replaced the last patch with 3 patches.

  The first of the 3 patches removed the hack of reading System.map
  with properly reading the Elf symbol table to find start_mcount_loc
  and stop_mcount_loc.

  The second patch adds the call to "nm -S vmlinux" to get the sizes
  of each function.

  The previous last patch would just check the zeroed out values and compare
  them to kaslr_offset(). Instead, this time, the last patch adds a new
  ftrace_mcount_skip that is used to simply skip over the first entries
  that the sorttable.c moved to the beginning, as they were the weak functions
  that were found.


Steven Rostedt (16):
      scripts/sorttable: Remove unused macro defines
      scripts/sorttable: Remove unused write functions
      scripts/sorttable: Remove unneeded Elf_Rel
      scripts/sorttable: Have the ORC code use the _r() functions to read
      scripts/sorttable: Make compare_extable() into two functions
      scripts/sorttable: Convert Elf_Ehdr to union
      scripts/sorttable: Replace Elf_Shdr Macro with a union
      scripts/sorttable: Convert Elf_Sym MACRO over to a union
      scripts/sorttable: Add helper functions for Elf_Ehdr
      scripts/sorttable: Add helper functions for Elf_Shdr
      scripts/sorttable: Add helper functions for Elf_Sym
      scripts/sorttable: Use uint64_t for mcount sorting
      scripts/sorttable: Move code from sorttable.h into sorttable.c
      scripts/sorttable: Get start/stop_mcount_loc from ELF file directly
      scripts/sorttable: Zero out weak functions in mcount_loc table
      scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions

----
 kernel/trace/ftrace.c   |  16 +-
 scripts/link-vmlinux.sh |   4 +-
 scripts/sorttable.c     | 834 ++++++++++++++++++++++++++++++++++++++++++++----
 scripts/sorttable.h     | 497 -----------------------------
 4 files changed, 794 insertions(+), 557 deletions(-)
 delete mode 100644 scripts/sorttable.h

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v2 01/16] scripts/sorttable: Remove unused macro defines
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 02/16] scripts/sorttable: Remove unused write functions Steven Rostedt
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.h | 27 ---------------------------
 1 file changed, 27 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 7bd0184380d3..2a9ec5046e9a 100644
--- 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)
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 02/16] scripts/sorttable: Remove unused write functions
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 01/16] scripts/sorttable: Remove unused macro defines Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 03/16] scripts/sorttable: Remove unneeded Elf_Rel Steven Rostedt
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 26 --------------------------
 1 file changed, 26 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 83cdb843d92f..4dcdbf7a5e26 100644
--- 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 *x)
 	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 fname, void *addr)
 		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",
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 03/16] scripts/sorttable: Remove unneeded Elf_Rel
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 01/16] scripts/sorttable: Remove unused macro defines Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 02/16] scripts/sorttable: Remove unused write functions Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 04/16] scripts/sorttable: Have the ORC code use the _r() functions to read Steven Rostedt
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

The code had references to initialize the Elf_Rel relocation tables, but
it was never used. Remove it.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.h | 23 ++---------------------
 1 file changed, 2 insertions(+), 21 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 2a9ec5046e9a..aa7a8499a516 100644
--- 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
@@ -245,14 +242,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;
@@ -276,23 +269,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));
@@ -394,10 +379,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);
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 04/16] scripts/sorttable: Have the ORC code use the _r() functions to read
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (2 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 03/16] scripts/sorttable: Remove unneeded Elf_Rel Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 05/16] scripts/sorttable: Make compare_extable() into two functions Steven Rostedt
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index aa7a8499a516..7c06a754e31a 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -296,14 +296,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 */
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 05/16] scripts/sorttable: Make compare_extable() into two functions
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (3 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 04/16] scripts/sorttable: Have the ORC code use the _r() functions to read Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 06/16] scripts/sorttable: Convert Elf_Ehdr to union Steven Rostedt
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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;

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 20 ++++++++++++++++++++
 scripts/sorttable.h | 14 --------------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 4dcdbf7a5e26..3e2c17e91485 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -173,6 +173,26 @@ static inline unsigned int get_secindex(unsigned int shndx,
 	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
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 7c06a754e31a..58e9cebe8362 100644
--- 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
@@ -157,17 +154,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;
 
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 06/16] scripts/sorttable: Convert Elf_Ehdr to union
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (4 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 05/16] scripts/sorttable: Make compare_extable() into two functions Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 07/16] scripts/sorttable: Replace Elf_Shdr Macro with a union Steven Rostedt
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 36 ++++++++++++++++++++----------------
 scripts/sorttable.h | 12 ++++++------
 2 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 3e2c17e91485..67cbbfc8214d 100644
--- 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_data(char *extab_image, int image_size)
 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 fname, void *addr)
 		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 fname, void *addr)
 		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 fname, void *addr)
 		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;
 	}
 
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 58e9cebe8362..eff204958ffc 100644
--- 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)
@@ -219,7 +219,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;
@@ -246,12 +246,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);
 
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 07/16] scripts/sorttable: Replace Elf_Shdr Macro with a union
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (5 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 06/16] scripts/sorttable: Convert Elf_Ehdr to union Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 08/16] scripts/sorttable: Convert Elf_Sym MACRO over to " Steven Rostedt
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 10 ++++++
 scripts/sorttable.h | 74 +++++++++++++++++++++++++--------------------
 2 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 67cbbfc8214d..94497b8ab04c 100644
--- 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 *a, const void *b)
 	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
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index eff204958ffc..034ce8560dad 100644
--- 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
@@ -168,8 +165,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;
 
@@ -219,10 +216,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;
@@ -232,7 +230,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
@@ -246,34 +247,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;
 		}
@@ -282,14 +289,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 */
@@ -352,22 +359,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;
@@ -385,13 +392,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);
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 08/16] scripts/sorttable: Convert Elf_Sym MACRO over to a union
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (6 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 07/16] scripts/sorttable: Replace Elf_Shdr Macro with a union Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 09/16] scripts/sorttable: Add helper functions for Elf_Ehdr Steven Rostedt
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c |  5 +++++
 scripts/sorttable.h | 25 ++++++++++++++-----------
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 94497b8ab04c..57792cf2aa89 100644
--- 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 *);
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 034ce8560dad..a365a8bc405a 100644
--- 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
@@ -227,10 +224,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;
@@ -373,12 +373,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;
@@ -392,13 +395,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 */
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 09/16] scripts/sorttable: Add helper functions for Elf_Ehdr
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (7 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 08/16] scripts/sorttable: Convert Elf_Sym MACRO over to " Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 10/16] scripts/sorttable: Add helper functions for Elf_Shdr Steven Rostedt
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 25 +++++++++++++++++++++++++
 scripts/sorttable.h | 20 ++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 57792cf2aa89..5dfa734eff09 100644
--- 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
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a365a8bc405a..3855f2ad0e73 100644
--- 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)
@@ -247,16 +259,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);
 
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 10/16] scripts/sorttable: Add helper functions for Elf_Shdr
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (8 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 09/16] scripts/sorttable: Add helper functions for Elf_Ehdr Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 11/16] scripts/sorttable: Add helper functions for Elf_Sym Steven Rostedt
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 42 +++++++++++++++++++++++++++++
 scripts/sorttable.h | 66 +++++++++++++++++++++++++++++----------------
 2 files changed, 85 insertions(+), 23 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 5dfa734eff09..b2b96ff261d6 100644
--- 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
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 3855f2ad0e73..a391757aaff0 100644
--- 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)
@@ -174,8 +195,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;
 
@@ -264,18 +285,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"))
@@ -283,9 +304,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 */
@@ -301,14 +322,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 */
@@ -371,23 +392,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) {
@@ -412,9 +432,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);
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 11/16] scripts/sorttable: Add helper functions for Elf_Sym
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (9 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 10/16] scripts/sorttable: Add helper functions for Elf_Shdr Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 12/16] scripts/sorttable: Use uint64_t for mcount sorting Steven Rostedt
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
 scripts/sorttable.h | 30 +++++++++++++++--------------
 2 files changed, 63 insertions(+), 14 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index b2b96ff261d6..20615de18276 100644
--- 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
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a391757aaff0..a1c9bdd6b5dd 100644
--- 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)
@@ -411,9 +414,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;
@@ -427,14 +430,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);
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 12/16] scripts/sorttable: Use uint64_t for mcount sorting
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (10 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 11/16] scripts/sorttable: Add helper functions for Elf_Sym Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 13/16] scripts/sorttable: Move code from sorttable.h into sorttable.c Steven Rostedt
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.h | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a1c9bdd6b5dd..b9c0716ee72c 100644
--- 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)
@@ -190,25 +190,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];
@@ -274,8 +274,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;
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 13/16] scripts/sorttable: Move code from sorttable.h into sorttable.c
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (11 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 12/16] scripts/sorttable: Use uint64_t for mcount sorting Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-03 23:02   ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 14/16] scripts/sorttable: Get start/stop_mcount_loc from ELF file directly Steven Rostedt
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 470 ++++++++++++++++++++++++++++++++++++++++--
 scripts/sorttable.h | 482 --------------------------------------------
 2 files changed, 457 insertions(+), 495 deletions(-)
 delete mode 100644 scripts/sorttable.h

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 20615de18276..da9e1a82e886 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -327,10 +327,420 @@ 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
-#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;
+
+
+#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
+/* ORC unwinder only support X86_64 */
+#include <asm/orc_types.h>
+
+#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;
+	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);
+	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
+#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;
+}
 
 static int compare_relative_table(const void *a, const void *b)
 {
@@ -399,7 +809,6 @@ static void sort_relative_table_with_data(char *extab_image, int image_size)
 
 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 +871,64 @@ static int do_file(char const *const fname, void *addr)
 		    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[])
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
deleted file mode 100644
index b9c0716ee72c..000000000000
--- a/scripts/sorttable.h
+++ /dev/null
@@ -1,482 +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 <shile.zhang@linux.alibaba.com>
- *
- * 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 <jpoimboe@redhat.com>
- *
- * Some of this code was taken out of recordmcount.h written by:
- *
- * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
- * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, 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 <asm/orc_types.h>
-
-#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;
-	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);
-	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;
-}
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 14/16] scripts/sorttable: Get start/stop_mcount_loc from ELF file directly
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (12 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 13/16] scripts/sorttable: Move code from sorttable.h into sorttable.c Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 15/16] scripts/sorttable: Zero out weak functions in mcount_loc table Steven Rostedt
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/sorttable.c | 96 +++++++++++++++++++++------------------------
 1 file changed, 45 insertions(+), 51 deletions(-)

diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index da9e1a82e886..c26e71e6ec6b 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -469,42 +469,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)
@@ -535,8 +534,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
 #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
 	unsigned int orc_ip_size = 0;
@@ -574,15 +571,9 @@ 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
-
 #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
 		/* locate the ORC unwind tables */
 		if (!strcmp(secstrings + idx, ".orc_unwind_ip")) {
@@ -624,23 +615,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;
@@ -660,6 +634,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 {
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 15/16] scripts/sorttable: Zero out weak functions in mcount_loc table
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (13 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 14/16] scripts/sorttable: Get start/stop_mcount_loc from ELF file directly Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-01-02 23:26 ` [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions Steven Rostedt
  2025-01-02 23:31 ` [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

In preparation for removing weak functions from available_filter_functions,
have the sorttable.c code that sorts the mcount regions during the build
modified to take a "nm -S vmlinux" as 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.
This will move them all to the beginning of the mcount_loc section. This
will allow for the ftrace code to be able to skip them in one go.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 scripts/link-vmlinux.sh |   4 +-
 scripts/sorttable.c     | 129 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index d853ddb3b28c..976808c46665 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -177,12 +177,14 @@ mksysmap()
 
 sorttable()
 {
-	${objtree}/scripts/sorttable ${1}
+	${NM} -S ${1} > .tmp_vmlinux.nm-sort
+	${objtree}/scripts/sorttable -s .tmp_vmlinux.nm-sort ${1}
 }
 
 cleanup()
 {
 	rm -f .btf.*
+	rm -f .tmp_vmlinux.nm-sort
 	rm -f System.map
 	rm -f vmlinux
 	rm -f vmlinux.map
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index c26e71e6ec6b..1a2b420a4929 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -446,6 +446,98 @@ static void *sort_orctable(void *arg)
 #endif
 
 #ifdef MCOUNT_SORT_ENABLED
+struct func_info {
+	uint64_t	addr;
+	uint64_t	size;
+};
+
+/* List of functions created by: nm -S vmlinux */
+static struct func_info *function_list;
+static int function_list_size;
+
+/* Allocate functions in 1k blocks */
+#define FUNC_BLK_SIZE	1024
+#define FUNC_BLK_MASK	(FUNC_BLK_SIZE - 1)
+
+static int add_field(uint64_t addr, uint64_t size)
+{
+	struct func_info *fi;
+	int fsize = function_list_size;
+
+	if (!(fsize & FUNC_BLK_MASK)) {
+		fsize += FUNC_BLK_SIZE;
+		fi = realloc(function_list, fsize * sizeof(struct func_info));
+		if (!fi)
+			return -1;
+		function_list = fi;
+	}
+	fi = &function_list[function_list_size++];
+	fi->addr = addr;
+	fi->size = size;
+	return 0;
+}
+
+/* Only return match if the address lies inside the function size */
+static int cmp_func_addr(const void *K, const void *A)
+{
+	uint64_t key = *(const uint64_t *)K;
+	const struct func_info *a = A;
+
+	if (key < a->addr)
+		return -1;
+	return key >= a->addr + a->size;
+}
+
+/* Find the function in function list that is bounded by the function size */
+static int find_func(uint64_t key)
+{
+	return bsearch(&key, function_list, function_list_size,
+		       sizeof(struct func_info), cmp_func_addr) != NULL;
+}
+
+static int cmp_funcs(const void *A, const void *B)
+{
+	const struct func_info *a = A;
+	const struct func_info *b = B;
+
+	if (a->addr < b->addr)
+		return -1;
+	return a->addr > b->addr;
+}
+
+static int parse_symbols(const char *fname)
+{
+	FILE *fp;
+	char addr_str[20]; /* Only need 17, but round up to next int size */
+	char size_str[20];
+	char type;
+
+	fp = fopen(fname, "r");
+	if (!fp) {
+		perror(fname);
+		return -1;
+	}
+
+	while (fscanf(fp, "%16s %16s %c %*s\n", addr_str, size_str, &type) == 3) {
+		uint64_t addr;
+		uint64_t size;
+
+		/* Only care about functions */
+		if (type != 't' && type != 'T')
+			continue;
+
+		addr = strtoull(addr_str, NULL, 16);
+		size = strtoull(size_str, NULL, 16);
+		if (add_field(addr, size) < 0)
+			return -1;
+	}
+	fclose(fp);
+
+	qsort(function_list, function_list_size, sizeof(struct func_info), cmp_funcs);
+
+	return 0;
+}
+
 static pthread_t mcount_sort_thread;
 
 struct elf_mcount_loc {
@@ -463,6 +555,22 @@ static void *sort_mcount_loc(void *arg)
 					+ 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;
+	void *end_loc = start_loc + count;
+
+	/* zero out any locations not found by function list */
+	if (function_list_size) {
+		for (void *ptr = start_loc; ptr < end_loc; 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;
+			}
+		}
+	}
 
 	qsort(start_loc, count/long_size, long_size, compare_extable);
 	return NULL;
@@ -502,6 +610,8 @@ static void get_mcount_loc(struct elf_mcount_loc *emloc, Elf_Shdr *symtab_sec,
 		return;
 	}
 }
+#else /* MCOUNT_SORT_ENABLED */
+static inline int parse_symbols(const char *fname) { return 0; }
 #endif
 
 static int do_sort(Elf_Ehdr *ehdr,
@@ -930,14 +1040,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;
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (14 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 15/16] scripts/sorttable: Zero out weak functions in mcount_loc table Steven Rostedt
@ 2025-01-02 23:26 ` Steven Rostedt
  2025-02-05  0:13   ` Martin Kelly
  2025-01-02 23:31 ` [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
  16 siblings, 1 reply; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:26 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

From: Steven Rostedt <rostedt@goodmis.org>

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___<invalid-offset>

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.

A new initdata variable is added: ftrace_mcount_skip
The sorttable will update that to the number of functions at the start of
the mcount_loc section that should be skipped. As it zeros out the weak
functions before sorting, they end up all at the start of the section.
This variable states how many of them to skip over.

On boot up, when the ftrace table is created from the mcount_loc section,
it will start at the start_mcount_loc + ftrace_mcount_skip. This stops the
weak functions from ever being added to the ftrace table and also keeps
from needing place holders in available_filter_functions.

Before:

 ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l
 556

After:

 ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l
 0

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 kernel/trace/ftrace.c | 16 +++++++++++++---
 scripts/sorttable.c   | 36 ++++++++++++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 9b17efb1a87d..1b8cb4ebd285 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -7747,10 +7747,14 @@ int __init __weak ftrace_dyn_arch_init(void)
 	return 0;
 }
 
+/* This is set in scripts/sorttable.c */
+int ftrace_mcount_skip __initdata;
+
 void __init ftrace_init(void)
 {
 	extern unsigned long __start_mcount_loc[];
 	extern unsigned long __stop_mcount_loc[];
+	unsigned long *start_addr = __start_mcount_loc;
 	unsigned long count, flags;
 	int ret;
 
@@ -7761,6 +7765,14 @@ void __init ftrace_init(void)
 		goto failed;
 
 	count = __stop_mcount_loc - __start_mcount_loc;
+
+	/*
+	 * scripts/sorttable.c will set ftrace_mcount_skip to state
+	 * how many functions to skip in the __mcount_loc section.
+	 * These would have been weak functions.
+	 */
+	count -= ftrace_mcount_skip;
+	start_addr += ftrace_mcount_skip;
 	if (!count) {
 		pr_info("ftrace: No functions to be traced?\n");
 		goto failed;
@@ -7769,9 +7781,7 @@ void __init ftrace_init(void)
 	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);
+	ret = ftrace_process_locs(NULL, start_addr, __stop_mcount_loc);
 	if (ret) {
 		pr_warn("ftrace: failed to allocate entries for functions\n");
 		goto failed;
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index 1a2b420a4929..506172898fd8 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -543,6 +543,7 @@ static pthread_t mcount_sort_thread;
 struct elf_mcount_loc {
 	Elf_Ehdr *ehdr;
 	Elf_Shdr *init_data_sec;
+	Elf_Sym *ftrace_skip_sym;
 	uint64_t start_mcount_loc;
 	uint64_t stop_mcount_loc;
 };
@@ -554,9 +555,17 @@ static void *sort_mcount_loc(void *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;
+	uint32_t *skip_addr = NULL;
 	unsigned char *start_loc = (void *)emloc->ehdr + offset;
 	void *end_loc = start_loc + count;
 
+	if (emloc->ftrace_skip_sym) {
+		offset = sym_value(emloc->ftrace_skip_sym) -
+			shdr_addr(emloc->init_data_sec) +
+			shdr_offset(emloc->init_data_sec);
+		skip_addr = (void *)emloc->ehdr + offset;
+	}
+
 	/* zero out any locations not found by function list */
 	if (function_list_size) {
 		for (void *ptr = start_loc; ptr < end_loc; ptr += long_size) {
@@ -573,6 +582,25 @@ static void *sort_mcount_loc(void *arg)
 	}
 
 	qsort(start_loc, count/long_size, long_size, compare_extable);
+
+	/* Now set how many functions need to be skipped */
+	for (void *ptr = start_loc; skip_addr && ptr < end_loc; ptr += long_size) {
+		uint64_t val;
+
+		if (long_size == 4)
+			val = *(uint32_t *)ptr;
+		else
+			val = *(uint64_t *)ptr;
+		if (val) {
+			uint32_t skip;
+
+			/* Update the ftrace_mcount_skip to skip these functions */
+			val = ptr - (void *)start_loc;
+			skip = val / long_size;
+			w(r(&skip), skip_addr);
+			break;
+		}
+	}
 	return NULL;
 }
 
@@ -590,11 +618,15 @@ static void get_mcount_loc(struct elf_mcount_loc *emloc, Elf_Shdr *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)
+			if (++found == 3)
 				break;
 		} else if (!strcmp(strtab + sym_name(sym), "__stop_mcount_loc")) {
 			emloc->stop_mcount_loc = sym_value(sym);
-			if (++found == 2)
+			if (++found == 3)
+				break;
+		} else if (!strcmp(strtab + sym_name(sym), "ftrace_mcount_skip")) {
+			emloc->ftrace_skip_sym = sym;
+			if (++found == 3)
 				break;
 		}
 		sym = (void *)sym + symentsize;
-- 
2.45.2



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions
  2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
                   ` (15 preceding siblings ...)
  2025-01-02 23:26 ` [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions Steven Rostedt
@ 2025-01-02 23:31 ` Steven Rostedt
  16 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-02 23:31 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

On Thu, 02 Jan 2025 18:26:09 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:

> Steven Rostedt (16):
>       scripts/sorttable: Remove unused macro defines
>       scripts/sorttable: Remove unused write functions
>       scripts/sorttable: Remove unneeded Elf_Rel
>       scripts/sorttable: Have the ORC code use the _r() functions to read
>       scripts/sorttable: Make compare_extable() into two functions
>       scripts/sorttable: Convert Elf_Ehdr to union
>       scripts/sorttable: Replace Elf_Shdr Macro with a union
>       scripts/sorttable: Convert Elf_Sym MACRO over to a union
>       scripts/sorttable: Add helper functions for Elf_Ehdr
>       scripts/sorttable: Add helper functions for Elf_Shdr
>       scripts/sorttable: Add helper functions for Elf_Sym
>       scripts/sorttable: Use uint64_t for mcount sorting
>       scripts/sorttable: Move code from sorttable.h into sorttable.c
>       scripts/sorttable: Get start/stop_mcount_loc from ELF file directly

Note. These first 14 patches are simply clean up patches to the sorttable.c
code. I would like to start testing these and add them to linux-next, as I
do not believe they are controversial. They should not have any real
functional change, but it would still be good to test them on other
architectures outside of the mcount code.

The last two patches are what handle the weak functions in mcount_loc. I'll
hold off on those till after the v6.14 merge window.

-- Steve

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 13/16] scripts/sorttable: Move code from sorttable.h into sorttable.c
  2025-01-02 23:26 ` [PATCH v2 13/16] scripts/sorttable: Move code from sorttable.h into sorttable.c Steven Rostedt
@ 2025-01-03 23:02   ` Steven Rostedt
  0 siblings, 0 replies; 22+ messages in thread
From: Steven Rostedt @ 2025-01-03 23:02 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, linux-kbuild, bpf
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	Peter Zijlstra, Linus Torvalds, Masahiro Yamada,
	Nathan Chancellor, Nicolas Schier, Zheng Yejian, Martin Kelly,
	Christophe Leroy, Josh Poimboeuf

On Thu, 02 Jan 2025 18:26:22 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:

> diff --git a/scripts/sorttable.c b/scripts/sorttable.c
> index 20615de18276..da9e1a82e886 100644
> --- a/scripts/sorttable.c
> +++ b/scripts/sorttable.c
> @@ -327,10 +327,420 @@ 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
> -#include "sorttable.h"
> +

[..]

> +
> +#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)

My tests started to fail after this patch. It was the stack tracing tests
on x86_64. This patch removed the define of SORTTABLE_64, which stopped the
orc unwinder section from being sorted. :-p

Oops! When I post the stand-a-lone patches, this will be fixed.

-- Steve


> +/* ORC unwinder only support X86_64 */
> +#include <asm/orc_types.h>
> +
> +#define ERRSTR_MAXSZ	256
> +

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions
  2025-01-02 23:26 ` [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions Steven Rostedt
@ 2025-02-05  0:13   ` Martin Kelly
  2025-02-05  0:35     ` Steven Rostedt
  0 siblings, 1 reply; 22+ messages in thread
From: Martin Kelly @ 2025-02-05  0:13 UTC (permalink / raw)
  To: rostedt@goodmis.org, linux-kernel@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org, bpf@vger.kernel.org,
	linux-kbuild@vger.kernel.org
  Cc: masahiroy@kernel.org, akpm@linux-foundation.org,
	jpoimboe@redhat.com, peterz@infradead.org, mark.rutland@arm.com,
	mathieu.desnoyers@efficios.com, mhiramat@kernel.org,
	torvalds@linux-foundation.org, nicolas@fjasle.eu,
	nathan@kernel.org, zhengyejian1@huawei.com,
	christophe.leroy@csgroup.eu

On Thu, 2025-01-02 at 18:26 -0500, Steven Rostedt wrote:
> From: Steven Rostedt <rostedt@goodmis.org>
> 
> 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.
> 

I'm not necessarily a qualified reviewer for this patch, but I'm very
interested in seeing it or a similar solution get merged, as the impact
when it hits is significant (silent failure) and not easy to detect or
work around. Is there any obstacle left in getting this one merged
other than further reviews?

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions
  2025-02-05  0:13   ` Martin Kelly
@ 2025-02-05  0:35     ` Steven Rostedt
  2025-02-05 16:00       ` Martin Kelly
  0 siblings, 1 reply; 22+ messages in thread
From: Steven Rostedt @ 2025-02-05  0:35 UTC (permalink / raw)
  To: Martin Kelly
  Cc: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
	bpf@vger.kernel.org, linux-kbuild@vger.kernel.org,
	masahiroy@kernel.org, akpm@linux-foundation.org,
	jpoimboe@redhat.com, peterz@infradead.org, mark.rutland@arm.com,
	mathieu.desnoyers@efficios.com, mhiramat@kernel.org,
	torvalds@linux-foundation.org, nicolas@fjasle.eu,
	nathan@kernel.org, zhengyejian1@huawei.com,
	christophe.leroy@csgroup.eu

On Wed, 5 Feb 2025 00:13:26 +0000
Martin Kelly <martin.kelly@crowdstrike.com> wrote:

> I'm not necessarily a qualified reviewer for this patch, but I'm very
> interested in seeing it or a similar solution get merged, as the impact
> when it hits is significant (silent failure) and not easy to detect or
> work around. Is there any obstacle left in getting this one merged
> other than further reviews?

A version of the patches 1-14 was merged this merge window, with some
tweaks. I plan on rebasing patches 15 and 16 on top of that and
resubmitting. I just have some other things I'm finishing up.

Thanks,

-- Steve

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Re: [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions
  2025-02-05  0:35     ` Steven Rostedt
@ 2025-02-05 16:00       ` Martin Kelly
  0 siblings, 0 replies; 22+ messages in thread
From: Martin Kelly @ 2025-02-05 16:00 UTC (permalink / raw)
  To: rostedt@goodmis.org
  Cc: bpf@vger.kernel.org, masahiroy@kernel.org,
	zhengyejian1@huawei.com, torvalds@linux-foundation.org,
	mhiramat@kernel.org, mathieu.desnoyers@efficios.com,
	akpm@linux-foundation.org, linux-kernel@vger.kernel.org,
	nathan@kernel.org, nicolas@fjasle.eu, christophe.leroy@csgroup.eu,
	mark.rutland@arm.com, peterz@infradead.org,
	linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org,
	jpoimboe@redhat.com

On Tue, 2025-02-04 at 19:35 -0500, Steven Rostedt wrote:
> On Wed, 5 Feb 2025 00:13:26 +0000
> Martin Kelly <martin.kelly@crowdstrike.com> wrote:
> 
> > I'm not necessarily a qualified reviewer for this patch, but I'm
> > very
> > interested in seeing it or a similar solution get merged, as the
> > impact
> > when it hits is significant (silent failure) and not easy to detect
> > or
> > work around. Is there any obstacle left in getting this one merged
> > other than further reviews?
> 
> A version of the patches 1-14 was merged this merge window, with some
> tweaks. I plan on rebasing patches 15 and 16 on top of that and
> resubmitting. I just have some other things I'm finishing up.
> 
> Thanks,
> 
> -- Steve

Awesome, thanks!

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2025-02-05 16:36 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-02 23:26 [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 01/16] scripts/sorttable: Remove unused macro defines Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 02/16] scripts/sorttable: Remove unused write functions Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 03/16] scripts/sorttable: Remove unneeded Elf_Rel Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 04/16] scripts/sorttable: Have the ORC code use the _r() functions to read Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 05/16] scripts/sorttable: Make compare_extable() into two functions Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 06/16] scripts/sorttable: Convert Elf_Ehdr to union Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 07/16] scripts/sorttable: Replace Elf_Shdr Macro with a union Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 08/16] scripts/sorttable: Convert Elf_Sym MACRO over to " Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 09/16] scripts/sorttable: Add helper functions for Elf_Ehdr Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 10/16] scripts/sorttable: Add helper functions for Elf_Shdr Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 11/16] scripts/sorttable: Add helper functions for Elf_Sym Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 12/16] scripts/sorttable: Use uint64_t for mcount sorting Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 13/16] scripts/sorttable: Move code from sorttable.h into sorttable.c Steven Rostedt
2025-01-03 23:02   ` Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 14/16] scripts/sorttable: Get start/stop_mcount_loc from ELF file directly Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 15/16] scripts/sorttable: Zero out weak functions in mcount_loc table Steven Rostedt
2025-01-02 23:26 ` [PATCH v2 16/16] scripts/sorttable: ftrace: Do not add weak functions to available_filter_functions Steven Rostedt
2025-02-05  0:13   ` Martin Kelly
2025-02-05  0:35     ` Steven Rostedt
2025-02-05 16:00       ` Martin Kelly
2025-01-02 23:31 ` [PATCH v2 00/16] scripts/sorttable: ftrace: Remove place holders for weak functions in available_filter_functions Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).