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
This commit is contained in:
Родитель
efb11fdb3e
Коммит
0646c28b41
|
@ -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 */
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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; \
|
||||
} \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче