Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Use target file endianness instead of a compiled constant

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.rao@linux.vnet.ibm.com>
Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20221114175754.1131267-10-sv@linux.ibm.com

authored by

Christophe Leroy and committed by
Michael Ellerman
0646c28b efb11fdb

+30 -31
-9
tools/objtool/arch/x86/include/arch/endianness.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - #ifndef _ARCH_ENDIANNESS_H 3 - #define _ARCH_ENDIANNESS_H 4 - 5 - #include <endian.h> 6 - 7 - #define __TARGET_BYTE_ORDER __LITTLE_ENDIAN 8 - 9 - #endif /* _ARCH_ENDIANNESS_H */
+1 -1
tools/objtool/check.c
··· 2100 2100 return -1; 2101 2101 } 2102 2102 2103 - cfi.cfa.offset = bswap_if_needed(hint->sp_offset); 2103 + cfi.cfa.offset = bswap_if_needed(file->elf, hint->sp_offset); 2104 2104 cfi.type = hint->type; 2105 2105 cfi.end = hint->end; 2106 2106
+16 -16
tools/objtool/include/objtool/endianness.h
··· 2 2 #ifndef _OBJTOOL_ENDIANNESS_H 3 3 #define _OBJTOOL_ENDIANNESS_H 4 4 5 - #include <arch/endianness.h> 6 5 #include <linux/kernel.h> 7 6 #include <endian.h> 8 - 9 - #ifndef __TARGET_BYTE_ORDER 10 - #error undefined arch __TARGET_BYTE_ORDER 11 - #endif 12 - 13 - #if __BYTE_ORDER != __TARGET_BYTE_ORDER 14 - #define __NEED_BSWAP 1 15 - #else 16 - #define __NEED_BSWAP 0 17 - #endif 7 + #include <objtool/elf.h> 18 8 19 9 /* 20 - * Does a byte swap if target endianness doesn't match the host, i.e. cross 10 + * Does a byte swap if target file endianness doesn't match the host, i.e. cross 21 11 * compilation for little endian on big endian and vice versa. 22 12 * To be used for multi-byte values conversion, which are read from / about 23 13 * to be written to a target native endianness ELF file. 24 14 */ 25 - #define bswap_if_needed(val) \ 15 + static inline bool need_bswap(struct elf *elf) 16 + { 17 + return (__BYTE_ORDER == __LITTLE_ENDIAN) ^ 18 + (elf->ehdr.e_ident[EI_DATA] == ELFDATA2LSB); 19 + } 20 + 21 + #define bswap_if_needed(elf, val) \ 26 22 ({ \ 27 23 __typeof__(val) __ret; \ 24 + bool __need_bswap = need_bswap(elf); \ 28 25 switch (sizeof(val)) { \ 29 - case 8: __ret = __NEED_BSWAP ? bswap_64(val) : (val); break; \ 30 - case 4: __ret = __NEED_BSWAP ? bswap_32(val) : (val); break; \ 31 - case 2: __ret = __NEED_BSWAP ? bswap_16(val) : (val); break; \ 26 + case 8: \ 27 + __ret = __need_bswap ? bswap_64(val) : (val); break; \ 28 + case 4: \ 29 + __ret = __need_bswap ? bswap_32(val) : (val); break; \ 30 + case 2: \ 31 + __ret = __need_bswap ? bswap_16(val) : (val); break; \ 32 32 default: \ 33 33 BUILD_BUG(); break; \ 34 34 } \
+9 -2
tools/objtool/orc_dump.c
··· 76 76 GElf_Rela rela; 77 77 GElf_Sym sym; 78 78 Elf_Data *data, *symtab = NULL, *rela_orc_ip = NULL; 79 + struct elf dummy_elf = {}; 79 80 80 81 81 82 objname = _objname; ··· 94 93 WARN_ELF("elf_begin"); 95 94 return -1; 96 95 } 96 + 97 + if (!elf64_getehdr(elf)) { 98 + WARN_ELF("elf64_getehdr"); 99 + return -1; 100 + } 101 + memcpy(&dummy_elf.ehdr, elf64_getehdr(elf), sizeof(dummy_elf.ehdr)); 97 102 98 103 if (elf_getshdrnum(elf, &nr_sections)) { 99 104 WARN_ELF("elf_getshdrnum"); ··· 205 198 206 199 printf(" sp:"); 207 200 208 - print_reg(orc[i].sp_reg, bswap_if_needed(orc[i].sp_offset)); 201 + print_reg(orc[i].sp_reg, bswap_if_needed(&dummy_elf, orc[i].sp_offset)); 209 202 210 203 printf(" bp:"); 211 204 212 - print_reg(orc[i].bp_reg, bswap_if_needed(orc[i].bp_offset)); 205 + print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, orc[i].bp_offset)); 213 206 214 207 printf(" type:%s end:%d\n", 215 208 orc_type_name(orc[i].type), orc[i].end);
+2 -2
tools/objtool/orc_gen.c
··· 97 97 /* populate ORC data */ 98 98 orc = (struct orc_entry *)orc_sec->data->d_buf + idx; 99 99 memcpy(orc, o, sizeof(*orc)); 100 - orc->sp_offset = bswap_if_needed(orc->sp_offset); 101 - orc->bp_offset = bswap_if_needed(orc->bp_offset); 100 + orc->sp_offset = bswap_if_needed(elf, orc->sp_offset); 101 + orc->bp_offset = bswap_if_needed(elf, orc->bp_offset); 102 102 103 103 /* populate reloc for ip */ 104 104 if (elf_add_reloc_to_insn(elf, ip_sec, idx * sizeof(int), R_X86_64_PC32,
+2 -1
tools/objtool/special.c
··· 87 87 if (entry->feature) { 88 88 unsigned short feature; 89 89 90 - feature = bswap_if_needed(*(unsigned short *)(sec->data->d_buf + 90 + feature = bswap_if_needed(elf, 91 + *(unsigned short *)(sec->data->d_buf + 91 92 offset + 92 93 entry->feature)); 93 94 arch_handle_alternative(feature, alt);