The ftrace __mcount_loc buildtime sort does not work properly when the host is
32-bit and the target is 64-bit. sorttable parses the start and stop addresses
by calling strtoul on the buffer holding the hexadecimal string. Since the
target is 64-bit but unsigned long on 32-bit machines is 32 bits, strtoul,
and by extension the start and stop addresses, can max out to 2^32 - 1.

This patch adds a new macro, parse_addr, that corresponds to a strtoul
or strtoull call based on whether you are operating on a 32-bit ELF or
a 64-bit ELF. This way, the correct width is guaranteed whether or not
the host is 32-bit. This should cleanly apply on all of the 6.x stable
kernels.

Manually verified that the __mcount_loc section is sorted by parsing the
ELF and verified tests corresponding to CONFIG_FTRACE_SORT_STARTUP_TEST
for kernels built on a 32-bit and a 64-bit host.

Signed-off-by: Sahil Gupta <[email protected]>
---
 scripts/sorttable.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 7bd0184380d3..9ed7acca9f30 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -40,6 +40,7 @@
 #undef uint_t
 #undef _r
 #undef _w
+#undef parse_addr
 
 #ifdef SORTTABLE_64
 # define extable_ent_size      16
@@ -65,6 +66,7 @@
 # define uint_t                        uint64_t
 # define _r                    r8
 # define _w                    w8
+# define parse_addr(buf)       strtoull(buf, NULL, 16)
 #else
 # define extable_ent_size      8
 # define compare_extable       compare_extable_32
@@ -89,6 +91,7 @@
 # define uint_t                        uint32_t
 # define _r                    r
 # define _w                    w
+# define parse_addr(buf)       strtoul(buf, NULL, 16)
 #endif
 
 #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
@@ -246,13 +249,13 @@ static void get_mcount_loc(uint_t *_start, uint_t *_stop)
                len = strlen(start_buff);
                start_buff[len - 1] = '\0';
        }
-       *_start = strtoul(start_buff, NULL, 16);
+       *_start = parse_addr(start_buff);
 
        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);
+       *_stop = parse_addr(stop_buff);
 
        pclose(file_start);
        pclose(file_stop);
-- 
2.47.0


Reply via email to