Message ID | 7c503552c4bc1f0e1aa4775765f8f24e9d1b0a04.1648713067.git.christophe.leroy@csgroup.eu (mailing list archive) |
---|---|
State | RFC |
Headers | show |
Series | [RFC,v1] objtool: Use target file endianness instead of a compiled constant | expand |
Context | Check | Description |
---|---|---|
snowpatch_ozlabs/github-powerpc_kernel_qemu | success | Successfully ran 24 jobs. |
snowpatch_ozlabs/github-powerpc_sparse | success | Successfully ran 4 jobs. |
snowpatch_ozlabs/github-powerpc_clang | success | Successfully ran 7 jobs. |
On Thu, Mar 31, 2022 at 09:52:07AM +0200, Christophe Leroy wrote: > 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. > > +#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(GElf_Ehdr *ehdr) > +{ > + return (__BYTE_ORDER == __LITTLE_ENDIAN) ^ > + (ehdr->e_ident[EI_DATA] == ELFDATA2LSB); > +} > + > +#define bswap_if_needed(ehdr, val) \ > ({ \ > __typeof__(val) __ret; \ > + bool __need_bswap = need_bswap(ehdr); \ > 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; \ > } \ Far less painfull that I imagined it would be,.. but I think I prefer passing in elf, as opposed to elf->ehdr, would that work?
Le 31/03/2022 à 10:08, Peter Zijlstra a écrit : > On Thu, Mar 31, 2022 at 09:52:07AM +0200, Christophe Leroy wrote: >> 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. >> > >> +#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(GElf_Ehdr *ehdr) >> +{ >> + return (__BYTE_ORDER == __LITTLE_ENDIAN) ^ >> + (ehdr->e_ident[EI_DATA] == ELFDATA2LSB); >> +} >> + >> +#define bswap_if_needed(ehdr, val) \ >> ({ \ >> __typeof__(val) __ret; \ >> + bool __need_bswap = need_bswap(ehdr); \ >> 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; \ >> } \ > > Far less painfull that I imagined it would be,.. but I think I prefer > passing in elf, as opposed to elf->ehdr, would that work? That's what I wanted to do in the beginning, but we don't have it in orc_dump() Christophe
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 6de5085e3e5a..378d4e2de285 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1941,7 +1941,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->ehdr, 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..2c7469a7645b 100644 --- a/tools/objtool/include/objtool/endianness.h +++ b/tools/objtool/include/objtool/endianness.h @@ -2,33 +2,30 @@ #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(GElf_Ehdr *ehdr) +{ + return (__BYTE_ORDER == __LITTLE_ENDIAN) ^ + (ehdr->e_ident[EI_DATA] == ELFDATA2LSB); +} + +#define bswap_if_needed(ehdr, val) \ ({ \ __typeof__(val) __ret; \ + bool __need_bswap = need_bswap(ehdr); \ 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..5a51586c6ad2 100644 --- a/tools/objtool/orc_dump.c +++ b/tools/objtool/orc_dump.c @@ -198,11 +198,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(elf64_getehdr(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(elf64_getehdr(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..63c36ed284a5 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->ehdr, orc->sp_offset); + orc->bp_offset = bswap_if_needed(&elf->ehdr, 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..ae563c524416 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->ehdr, + *(unsigned short *)(sec->data->d_buf + offset + entry->feature)); arch_handle_alternative(feature, alt);
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. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> --- .../arch/x86/include/arch/endianness.h | 9 ------ tools/objtool/check.c | 2 +- tools/objtool/include/objtool/endianness.h | 29 +++++++++---------- tools/objtool/orc_dump.c | 4 +-- tools/objtool/orc_gen.c | 4 +-- tools/objtool/special.c | 3 +- 6 files changed, 20 insertions(+), 31 deletions(-) delete mode 100644 tools/objtool/arch/x86/include/arch/endianness.h