Adds a endianness test function called native_endianness(). It has very low overhead (possibly none) compared to a simple variable assignment. Signed-off-by: Andreas Robinson <andr345@xxxxxxxxx> --- depmod.c | 17 ++++------------- depmod.h | 15 --------------- modinfo.c | 22 ++-------------------- util.c | 12 ++++++++++++ util.h | 20 ++++++++++++++++++++ 5 files changed, 38 insertions(+), 48 deletions(-) diff --git a/depmod.c b/depmod.c index 30d870c..9b6fda7 100644 --- a/depmod.c +++ b/depmod.c @@ -261,18 +261,6 @@ static int ends_in(const char *name, const char *ext) return 0; } -/* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */ -int needconv(const char *elfhdr) -{ - union { short s; char c[2]; } endian_test; - - endian_test.s = 1; - if (endian_test.c[1] == 1) return elfhdr[EI_DATA] != ELFDATA2MSB; - if (endian_test.c[0] == 1) return elfhdr[EI_DATA] != ELFDATA2LSB; - else - abort(); -} - static struct module *grab_module(const char *dirname, const char *filename) { struct module *new; @@ -313,7 +301,7 @@ static struct module *grab_module(const char *dirname, const char *filename) new->pathname, ((char *)new->data)[EI_CLASS]); goto fail; } - new->conv = needconv(new->data); + new->conv = ((char *)new->data)[EI_DATA] != native_endianness(); return new; fail: @@ -1166,6 +1154,9 @@ int main(int argc, char *argv[]) int i; const char *config = NULL; + if (native_endianness() == 0) + abort(); + /* Don't print out any errors just yet, we might want to exec backwards compat version. */ opterr = 0; diff --git a/depmod.h b/depmod.h index decdf2e..32cab3d 100644 --- a/depmod.h +++ b/depmod.h @@ -60,19 +60,4 @@ struct module char pathname[0]; }; -#define END(x, conv) \ -({ \ - typeof(x) __x; \ - if (conv) __convert_endian(&(x), &(__x), sizeof(__x)); \ - else __x = (x); \ - __x; \ -}) - -static inline void __convert_endian(const void *src, void *dest, - unsigned int size) -{ - unsigned int i; - for (i = 0; i < size; i++) - ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; -} #endif /* MODINITTOOLS_DEPMOD_H */ diff --git a/modinfo.c b/modinfo.c index 2208b19..80e00d4 100644 --- a/modinfo.c +++ b/modinfo.c @@ -22,22 +22,8 @@ #endif static int elf_endian; -static int my_endian; -static inline void __endian(const void *src, void *dest, unsigned int size) -{ - unsigned int i; - for (i = 0; i < size; i++) - ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; -} - -#define TO_NATIVE(x) \ -({ \ - typeof(x) __x; \ - if (elf_endian != my_endian) __endian(&(x), &(__x), sizeof(__x)); \ - else __x = x; \ - __x; \ -}) +#define TO_NATIVE(x) END(x, elf_endian != native_endianness()) static void *get_section32(void *file, unsigned long *size, const char *name) { @@ -348,7 +334,6 @@ static void usage(const char *name) int main(int argc, char *argv[]) { - union { short s; char c[2]; } endian_test; const char *field = NULL; const char *kernel = NULL; char sep = '\n'; @@ -356,10 +341,7 @@ int main(int argc, char *argv[]) int opt, ret = 0; char *basedir = ""; - endian_test.s = 1; - if (endian_test.c[1] == 1) my_endian = ELFDATA2MSB; - else if (endian_test.c[0] == 1) my_endian = ELFDATA2LSB; - else + if (native_endianness() == 0) abort(); while ((opt = getopt_long(argc,argv,"adlpVhn0F:k:b:",options,NULL)) >= 0){ diff --git a/util.c b/util.c index b65b090..3a390f7 100644 --- a/util.c +++ b/util.c @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> #include "logging.h" #include "util.h" @@ -130,3 +131,14 @@ const char *next_string(const char *string, unsigned long *secsize) } return string; } + +/* + * Get CPU endianness. 0 = unknown, 1 = ELFDATA2LSB = little, 2 = ELFDATA2MSB = big + */ +int __attribute__ ((pure)) native_endianness() +{ + /* Encoding the endianness enums in a string and then reading that + * string as a 32-bit int, returns the correct endianness automagically. + */ + return (char) *((uint32_t*)("\1\0\0\2")); +} diff --git a/util.h b/util.h index 9d41529..60e85e1 100644 --- a/util.h +++ b/util.h @@ -10,6 +10,26 @@ char *underscores(char *string); const char *next_string(const char *string, unsigned long *secsize); +/* + * Change endianness of x if conv is true. + */ +#define END(x, conv) \ +({ \ + typeof(x) __x; \ + if (conv) __swap_bytes(&(x), &(__x), sizeof(__x)); \ + else __x = (x); \ + __x; \ +}) + +static inline void __swap_bytes(const void *src, void *dest, unsigned int size) +{ + unsigned int i; + for (i = 0; i < size; i++) + ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; +} + +int native_endianness(void); + #define streq(a,b) (strcmp((a),(b)) == 0) #define strstarts(a,start) (strncmp((a),(start), strlen(start)) == 0) #define my_basename(path) ((strrchr((path), '/') ?: (path) - 1) + 1) -- 1.5.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-modules" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html