Currently when x86_64 kernel is cross compiled on big endian hardware
ORC unwind table is not sorted correctly. Due to missing byte swaps and
treating size as 4-byte value ORC sections sizes end up as 0 and the
problem is silently ignored.

Make ORC unwind table sorting endianness aware.

Signed-off-by: Vasily Gorbik <[email protected]>
---
 This goes on top of the patch series:
 
http://lkml.kernel.org/r/cover.thread-1e2854.your-ad-here.call-01605220128-ext-6070@work.hours

 scripts/sorttable.h | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a2baa2fefb13..99f3fa1767d1 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -59,6 +59,8 @@
 # define uint_t                        uint64_t
 # define _r                    r8
 # define _w                    w8
+# define _r4                   r
+# define _w4                   w
 #else
 # define extable_ent_size      8
 # define compare_extable       compare_extable_32
@@ -80,6 +82,8 @@
 # define uint_t                        uint32_t
 # define _r                    r
 # define _w                    w
+# define _r4                   r
+# define _w4                   w
 #endif
 
 #if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED)
@@ -98,7 +102,7 @@ pthread_t orc_sort_thread;
 
 static inline unsigned long orc_ip(const int *ip)
 {
-       return (unsigned long)ip + *ip;
+       return (unsigned long)ip + (int)_r4((uint32_t *)ip);
 }
 
 static int orc_sort_cmp(const void *_a, const void *_b)
@@ -158,7 +162,7 @@ static void *sort_orctable(void *arg)
        /* 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);
+               tmp_orc_ip_table[i] = (int)_r4((uint32_t *)&g_orc_ip_table[i]) 
+ i * sizeof(int);
        }
        memcpy(tmp_orc_table, g_orc_table, orc_size);
 
@@ -169,7 +173,7 @@ static void *sort_orctable(void *arg)
                        continue;
 
                /* convert back to relative address */
-               g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int);
+               _w4(tmp_orc_ip_table[idxs[i]] - i * sizeof(int), (uint32_t 
*)&g_orc_ip_table[i]);
                g_orc_table[i] = tmp_orc_table[idxs[i]];
        }
 
@@ -256,14 +260,12 @@ 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;
-                       g_orc_ip_table = (int *)((void *)ehdr +
-                                                  s->sh_offset);
+                       orc_ip_size = _r(&s->sh_size);
+                       g_orc_ip_table = (int *)((void *)ehdr + 
_r(&s->sh_offset));
                }
                if (!strcmp(secstrings + idx, ".orc_unwind")) {
-                       orc_size = s->sh_size;
-                       g_orc_table = (struct orc_entry *)((void *)ehdr +
-                                                            s->sh_offset);
+                       orc_size = _r(&s->sh_size);
+                       g_orc_table = (struct orc_entry *)((void *)ehdr + 
_r(&s->sh_offset));
                }
 #endif
        } /* for loop */
-- 
2.25.4

Reply via email to