162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci#ifndef _OBJTOOL_ENDIANNESS_H 362306a36Sopenharmony_ci#define _OBJTOOL_ENDIANNESS_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <endian.h> 762306a36Sopenharmony_ci#include <objtool/elf.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/* 1062306a36Sopenharmony_ci * Does a byte swap if target file endianness doesn't match the host, i.e. cross 1162306a36Sopenharmony_ci * compilation for little endian on big endian and vice versa. 1262306a36Sopenharmony_ci * To be used for multi-byte values conversion, which are read from / about 1362306a36Sopenharmony_ci * to be written to a target native endianness ELF file. 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_cistatic inline bool need_bswap(struct elf *elf) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci return (__BYTE_ORDER == __LITTLE_ENDIAN) ^ 1862306a36Sopenharmony_ci (elf->ehdr.e_ident[EI_DATA] == ELFDATA2LSB); 1962306a36Sopenharmony_ci} 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define bswap_if_needed(elf, val) \ 2262306a36Sopenharmony_ci({ \ 2362306a36Sopenharmony_ci __typeof__(val) __ret; \ 2462306a36Sopenharmony_ci bool __need_bswap = need_bswap(elf); \ 2562306a36Sopenharmony_ci switch (sizeof(val)) { \ 2662306a36Sopenharmony_ci case 8: \ 2762306a36Sopenharmony_ci __ret = __need_bswap ? bswap_64(val) : (val); break; \ 2862306a36Sopenharmony_ci case 4: \ 2962306a36Sopenharmony_ci __ret = __need_bswap ? bswap_32(val) : (val); break; \ 3062306a36Sopenharmony_ci case 2: \ 3162306a36Sopenharmony_ci __ret = __need_bswap ? bswap_16(val) : (val); break; \ 3262306a36Sopenharmony_ci default: \ 3362306a36Sopenharmony_ci BUILD_BUG(); break; \ 3462306a36Sopenharmony_ci } \ 3562306a36Sopenharmony_ci __ret; \ 3662306a36Sopenharmony_ci}) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#endif /* _OBJTOOL_ENDIANNESS_H */ 39