From: Christophe Leroy <christophe.le...@csgroup.eu>

Some architectures like powerpc support both endianness, it's
therefore not possible to fix the endianness via arch/endianness.h
because there is no easy way to get the target endianness at
build time.

Use the endianness recorded in the file objtool is working on.

Tested-by: Naveen N. Rao <naveen.n....@linux.vnet.ibm.com>
Reviewed-by: Naveen N. Rao <naveen.n....@linux.vnet.ibm.com>
Acked-by: Josh Poimboeuf <jpoim...@kernel.org>
Acked-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Signed-off-by: Christophe Leroy <christophe.le...@csgroup.eu>
---
 .../arch/x86/include/arch/endianness.h        |  9 ------
 tools/objtool/check.c                         |  2 +-
 tools/objtool/include/objtool/endianness.h    | 32 +++++++++----------
 tools/objtool/orc_dump.c                      | 11 +++++--
 tools/objtool/orc_gen.c                       |  4 +--
 tools/objtool/special.c                       |  3 +-
 6 files changed, 30 insertions(+), 31 deletions(-)
 delete mode 100644 tools/objtool/arch/x86/include/arch/endianness.h

diff --git a/tools/objtool/arch/x86/include/arch/endianness.h 
b/tools/objtool/arch/x86/include/arch/endianness.h
deleted file mode 100644
index 7c362527da20..000000000000
--- a/tools/objtool/arch/x86/include/arch/endianness.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _ARCH_ENDIANNESS_H
-#define _ARCH_ENDIANNESS_H
-
-#include <endian.h>
-
-#define __TARGET_BYTE_ORDER __LITTLE_ENDIAN
-
-#endif /* _ARCH_ENDIANNESS_H */
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 8427af808221..ad5dab175701 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2100,7 +2100,7 @@ static int read_unwind_hints(struct objtool_file *file)
                        return -1;
                }
 
-               cfi.cfa.offset = bswap_if_needed(hint->sp_offset);
+               cfi.cfa.offset = bswap_if_needed(file->elf, hint->sp_offset);
                cfi.type = hint->type;
                cfi.end = hint->end;
 
diff --git a/tools/objtool/include/objtool/endianness.h 
b/tools/objtool/include/objtool/endianness.h
index 10241341eff3..4d2aa9b0fe2f 100644
--- a/tools/objtool/include/objtool/endianness.h
+++ b/tools/objtool/include/objtool/endianness.h
@@ -2,33 +2,33 @@
 #ifndef _OBJTOOL_ENDIANNESS_H
 #define _OBJTOOL_ENDIANNESS_H
 
-#include <arch/endianness.h>
 #include <linux/kernel.h>
 #include <endian.h>
-
-#ifndef __TARGET_BYTE_ORDER
-#error undefined arch __TARGET_BYTE_ORDER
-#endif
-
-#if __BYTE_ORDER != __TARGET_BYTE_ORDER
-#define __NEED_BSWAP 1
-#else
-#define __NEED_BSWAP 0
-#endif
+#include <objtool/elf.h>
 
 /*
- * Does a byte swap if target endianness doesn't match the host, i.e. cross
+ * Does a byte swap if target file endianness doesn't match the host, i.e. 
cross
  * compilation for little endian on big endian and vice versa.
  * To be used for multi-byte values conversion, which are read from / about
  * to be written to a target native endianness ELF file.
  */
-#define bswap_if_needed(val)                                           \
+static inline bool need_bswap(struct elf *elf)
+{
+       return (__BYTE_ORDER == __LITTLE_ENDIAN) ^
+              (elf->ehdr.e_ident[EI_DATA] == ELFDATA2LSB);
+}
+
+#define bswap_if_needed(elf, val)                                      \
 ({                                                                     \
        __typeof__(val) __ret;                                          \
+       bool __need_bswap = need_bswap(elf);                            \
        switch (sizeof(val)) {                                          \
-       case 8: __ret = __NEED_BSWAP ? bswap_64(val) : (val); break;    \
-       case 4: __ret = __NEED_BSWAP ? bswap_32(val) : (val); break;    \
-       case 2: __ret = __NEED_BSWAP ? bswap_16(val) : (val); break;    \
+       case 8:                                                         \
+               __ret = __need_bswap ? bswap_64(val) : (val); break;    \
+       case 4:                                                         \
+               __ret = __need_bswap ? bswap_32(val) : (val); break;    \
+       case 2:                                                         \
+               __ret = __need_bswap ? bswap_16(val) : (val); break;    \
        default:                                                        \
                BUILD_BUG(); break;                                     \
        }                                                               \
diff --git a/tools/objtool/orc_dump.c b/tools/objtool/orc_dump.c
index f5a8508c42d6..4f1211fec82c 100644
--- a/tools/objtool/orc_dump.c
+++ b/tools/objtool/orc_dump.c
@@ -76,6 +76,7 @@ int orc_dump(const char *_objname)
        GElf_Rela rela;
        GElf_Sym sym;
        Elf_Data *data, *symtab = NULL, *rela_orc_ip = NULL;
+       struct elf dummy_elf = {};
 
 
        objname = _objname;
@@ -94,6 +95,12 @@ int orc_dump(const char *_objname)
                return -1;
        }
 
+       if (!elf64_getehdr(elf)) {
+               WARN_ELF("elf64_getehdr");
+               return -1;
+       }
+       memcpy(&dummy_elf.ehdr, elf64_getehdr(elf), sizeof(dummy_elf.ehdr));
+
        if (elf_getshdrnum(elf, &nr_sections)) {
                WARN_ELF("elf_getshdrnum");
                return -1;
@@ -198,11 +205,11 @@ int orc_dump(const char *_objname)
 
                printf(" sp:");
 
-               print_reg(orc[i].sp_reg, bswap_if_needed(orc[i].sp_offset));
+               print_reg(orc[i].sp_reg, bswap_if_needed(&dummy_elf, 
orc[i].sp_offset));
 
                printf(" bp:");
 
-               print_reg(orc[i].bp_reg, bswap_if_needed(orc[i].bp_offset));
+               print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, 
orc[i].bp_offset));
 
                printf(" type:%s end:%d\n",
                       orc_type_name(orc[i].type), orc[i].end);
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index dd3c64af9db2..1f22b7ebae58 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -97,8 +97,8 @@ static int write_orc_entry(struct elf *elf, struct section 
*orc_sec,
        /* populate ORC data */
        orc = (struct orc_entry *)orc_sec->data->d_buf + idx;
        memcpy(orc, o, sizeof(*orc));
-       orc->sp_offset = bswap_if_needed(orc->sp_offset);
-       orc->bp_offset = bswap_if_needed(orc->bp_offset);
+       orc->sp_offset = bswap_if_needed(elf, orc->sp_offset);
+       orc->bp_offset = bswap_if_needed(elf, orc->bp_offset);
 
        /* populate reloc for ip */
        if (elf_add_reloc_to_insn(elf, ip_sec, idx * sizeof(int), R_X86_64_PC32,
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index e2223dd91c37..9c8d827f69af 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -87,7 +87,8 @@ static int get_alt_entry(struct elf *elf, struct 
special_entry *entry,
        if (entry->feature) {
                unsigned short feature;
 
-               feature = bswap_if_needed(*(unsigned short *)(sec->data->d_buf +
+               feature = bswap_if_needed(elf,
+                                         *(unsigned short *)(sec->data->d_buf +
                                                              offset +
                                                              entry->feature));
                arch_handle_alternative(feature, alt);
-- 
2.31.1

Reply via email to