Skip to content

Commit

Permalink
detect endianness at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
liberize committed Dec 4, 2024
1 parent 8b40ede commit 4670f8c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 67 deletions.
105 changes: 39 additions & 66 deletions src/crc32.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,52 +11,25 @@
#include <stdint.h>
// size_t
#include <cstddef>
#include "utils.h"

#ifndef __LITTLE_ENDIAN
#define __LITTLE_ENDIAN 1234
#endif
#ifndef __BIG_ENDIAN
#define __BIG_ENDIAN 4321
#endif

// define endianess and some integer data types
#if defined(_MSC_VER) || defined(__MINGW32__)
// Windows always little endian
#define __BYTE_ORDER __LITTLE_ENDIAN
static inline uint32_t byteswap32(uint32_t x) {
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap32(x);
#else
// defines __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN
#include <sys/param.h>
#endif

// abort if byte order is undefined
#if !defined(__BYTE_ORDER)
#error undefined byte order, compile with -D__BYTE_ORDER=1234 (if little endian) or -D__BYTE_ORDER=4321 (big endian)
return (x >> 24) |
((x >> 8) & 0x0000FF00) |
((x << 8) & 0x00FF0000) |
(x << 24);
#endif

namespace
{
#if __BYTE_ORDER == __BIG_ENDIAN
/// swap endianess
static inline uint32_t swap(uint32_t x)
{
#if defined(__GNUC__) || defined(__clang__)
return __builtin_bswap32(x);
#else
return (x >> 24) |
((x >> 8) & 0x0000FF00) |
((x << 8) & 0x00FF0000) |
(x << 24);
#endif
}
#endif
} // anonymous namespace
}

// //////////////////////////////////////////////////////////
// constants

/// look-up table, already declared above
const uint32_t Crc32Lookup[8][256] =
{
static const uint32_t Crc32Lookup[8][256] = {
{
// note: the first number of every second row corresponds to the half-byte look-up table !
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,
Expand Down Expand Up @@ -341,39 +314,39 @@ const uint32_t Crc32Lookup[8][256] =


/// compute CRC32 (Slicing-by-8 algorithm)
uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32)
{
uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32) {
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
const uint32_t* current = (const uint32_t*) data;

// process eight bytes at once (Slicing-by-8)
while (length >= 8)
{
#if __BYTE_ORDER == __BIG_ENDIAN
uint32_t one = *current++ ^ swap(crc);
uint32_t two = *current++;
crc = Crc32Lookup[0][ two & 0xFF] ^
Crc32Lookup[1][(two>> 8) & 0xFF] ^
Crc32Lookup[2][(two>>16) & 0xFF] ^
Crc32Lookup[3][(two>>24) & 0xFF] ^
Crc32Lookup[4][ one & 0xFF] ^
Crc32Lookup[5][(one>> 8) & 0xFF] ^
Crc32Lookup[6][(one>>16) & 0xFF] ^
Crc32Lookup[7][(one>>24) & 0xFF];
#else
uint32_t one = *current++ ^ crc;
uint32_t two = *current++;
crc = Crc32Lookup[0][(two>>24) & 0xFF] ^
Crc32Lookup[1][(two>>16) & 0xFF] ^
Crc32Lookup[2][(two>> 8) & 0xFF] ^
Crc32Lookup[3][ two & 0xFF] ^
Crc32Lookup[4][(one>>24) & 0xFF] ^
Crc32Lookup[5][(one>>16) & 0xFF] ^
Crc32Lookup[6][(one>> 8) & 0xFF] ^
Crc32Lookup[7][ one & 0xFF];
#endif

length -= 8;
if (is_big_endian()) {
while (length >= 8) {
uint32_t one = *current++ ^ byteswap32(crc);
uint32_t two = *current++;
crc = Crc32Lookup[0][ two & 0xFF] ^
Crc32Lookup[1][(two>> 8) & 0xFF] ^
Crc32Lookup[2][(two>>16) & 0xFF] ^
Crc32Lookup[3][(two>>24) & 0xFF] ^
Crc32Lookup[4][ one & 0xFF] ^
Crc32Lookup[5][(one>> 8) & 0xFF] ^
Crc32Lookup[6][(one>>16) & 0xFF] ^
Crc32Lookup[7][(one>>24) & 0xFF];
length -= 8;
}
} else {
while (length >= 8) {
uint32_t one = *current++ ^ crc;
uint32_t two = *current++;
crc = Crc32Lookup[0][(two>>24) & 0xFF] ^
Crc32Lookup[1][(two>>16) & 0xFF] ^
Crc32Lookup[2][(two>> 8) & 0xFF] ^
Crc32Lookup[3][ two & 0xFF] ^
Crc32Lookup[4][(one>>24) & 0xFF] ^
Crc32Lookup[5][(one>>16) & 0xFF] ^
Crc32Lookup[6][(one>> 8) & 0xFF] ^
Crc32Lookup[7][ one & 0xFF];
length -= 8;
}
}

const uint8_t* currentChar = (const uint8_t*) current;
Expand Down
2 changes: 1 addition & 1 deletion src/mount.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ ssize_t get_elf_size(const char *path) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
bswap = ehdr.e_ident[EI_DATA] != ELFDATA2LSB;
#elif __BYTE_ORDER == __BIG_ENDIAN
bswap = ehdr.e_ident[EI_DATA] != ELFDATA2LSB;
bswap = ehdr.e_ident[EI_DATA] != ELFDATA2MSB;
#else
#error "Unknown machine endian"
#endif
Expand Down
5 changes: 5 additions & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
#define LOGD(fmt, ...) /* fprintf(stdout, OBF(fmt "\n"), ##__VA_ARGS__) */
#define LOGE(fmt, ...) fprintf(stderr, OBF(fmt "\n"), ##__VA_ARGS__)

inline int is_big_endian() {
int i = 1;
return ! *((char*) &i);
}

FORCE_INLINE std::string get_exe_path() {
char buf[PATH_MAX] = {0};
#if defined(__linux__) || defined(__CYGWIN__)
Expand Down

0 comments on commit 4670f8c

Please sign in to comment.