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 <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to