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 s.gupta@arista.com --- 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);