root/tools/objtool/include/objtool/endianness.h
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _OBJTOOL_ENDIANNESS_H
#define _OBJTOOL_ENDIANNESS_H

#include <linux/kernel.h>
#include <endian.h>

/*
 * 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.
 */
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;    \
        default:                                                        \
                BUILD_BUG(); break;                                     \
        }                                                               \
        __ret;                                                          \
})

#endif /* _OBJTOOL_ENDIANNESS_H */