summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2003-02-14 10:12:22 -0600
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2003-02-14 10:12:22 -0600
commitcbc98ae5392ed151ecf74ad41c3ec7b0cb5547bb (patch)
treea9941dde3d913607f39cba911a727453b5e08fd2
parent0e5064f80d41d75abbb10e040bbd7c600e08299c (diff)
kbuild: Figure endianness / word size at compile time
The helper file2alias had to jump through a lot of hoops because it did not know the host and target endianness / word size at compile time. We now build a small header scripts/elfconfig.h which contains this information for file2alias to use.
-rw-r--r--include/linux/mod_devicetable.h11
-rw-r--r--scripts/Makefile16
-rw-r--r--scripts/Makefile.build3
-rw-r--r--scripts/elfconfig.h4
-rw-r--r--scripts/empty.c1
-rw-r--r--scripts/file2alias.c181
-rw-r--r--scripts/file2alias_inc.c79
-rw-r--r--scripts/mk_elfconfig.c57
8 files changed, 203 insertions, 149 deletions
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index f285481d5c79..9baa5a448684 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -7,19 +7,18 @@
#ifndef LINUX_MOD_DEVICETABLE_H
#define LINUX_MOD_DEVICETABLE_H
-#include <linux/types.h>
-
#ifdef __KERNEL__
+#include <linux/types.h>
typedef unsigned long kernel_ulong_t;
#endif
#define PCI_ANY_ID (~0)
struct pci_device_id {
- unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */
- unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
- unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
- kernel_ulong_t driver_data; /* Data private to the driver */
+ __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
+ __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+ __u32 class, class_mask; /* (class,subclass,prog-if) triplet */
+ kernel_ulong_t driver_data; /* Data private to the driver */
};
/*
diff --git a/scripts/Makefile b/scripts/Makefile
index cf5a1862ea1d..59bdaae2e5b7 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -9,11 +9,23 @@
# conmakehash: Create arrays for initializing the kernel console tables
host-progs := fixdep split-include conmakehash docproc kallsyms modpost \
- file2alias
-build-targets := $(host-progs)
+ file2alias mk_elfconfig
+build-targets := $(host-progs) empty.o
# Let clean descend into subdirs
subdir- := lxdialog kconfig
# fixdep is needed to compile other host programs
$(addprefix $(obj)/,$(filter-out fixdep,$(host-progs))): $(obj)/fixdep
+
+# dependencies on generated files need to be listed explicitly
+
+$(obj)/file2alias: $(obj)/elfconfig.h
+
+quiet_cmd_elfconfig = MKTARGET $@
+ cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
+
+$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
+ $(call if_changed,elfconfig)
+
+targets += $(obj)/target.h
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index c32cfce4f9b8..a80f195f0c80 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -199,7 +199,8 @@ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
%.o: %.S FORCE
$(call if_changed_dep,as_o_S)
-targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS)
+targets += $(real-objs-y) $(real-objs-m) $(EXTRA_TARGETS) $(MAKECMDGOALS) \
+ $(build-targets)
# Build the compiled-in targets
# ---------------------------------------------------------------------------
diff --git a/scripts/elfconfig.h b/scripts/elfconfig.h
new file mode 100644
index 000000000000..807d67db5eed
--- /dev/null
+++ b/scripts/elfconfig.h
@@ -0,0 +1,4 @@
+#define KERNEL_ELFCLASS ELFCLASS32
+#define KERNEL_ELFDATA ELFDATA2LSB
+#define HOST_ELFCLASS ELFCLASS32
+#define HOST_ELFDATA ELFDATA2LSB
diff --git a/scripts/empty.c b/scripts/empty.c
new file mode 100644
index 000000000000..49839cc4ff26
--- /dev/null
+++ b/scripts/empty.c
@@ -0,0 +1 @@
+/* empty file to figure out endianness / word size */
diff --git a/scripts/file2alias.c b/scripts/file2alias.c
index 525a766bab3e..b638f80de910 100644
--- a/scripts/file2alias.c
+++ b/scripts/file2alias.c
@@ -14,13 +14,43 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <stdint.h>
+#include <endian.h>
-/* 32 bits: if it turns out to be 64, we add explicitly (see EXTRA_SIZE). */
-typedef int kernel_ulong_t;
-#include "../include/linux/types.h"
+#include "elfconfig.h"
+
+/* We use the ELF typedefs, since we can't rely on stdint.h being present. */
+
+#if KERNEL_ELFCLASS == ELFCLASS32
+typedef Elf32_Addr kernel_ulong_t;
+#else
+typedef Elf64_Addr kernel_ulong_t;
+#endif
+
+typedef Elf32_Word __u32;
+typedef Elf32_Half __u16;
+typedef unsigned char __u8;
+
+/* Big exception to the "don't include kernel headers into userspace, which
+ * even potentially has different endianness and word sizes, since
+ * we handle those differences explicitly below */
#include "../include/linux/mod_devicetable.h"
-static int switch_endian;
+#if KERNEL_ELFCLASS == ELFCLASS32
+
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+
+#else
+
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+
+#endif
+
+#if KERNEL_ELFDATA != HOST_ELFDATA
static void __endian(const void *src, void *dest, unsigned int size)
{
@@ -29,14 +59,22 @@ static void __endian(const void *src, void *dest, unsigned int size)
((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1];
}
+
+
#define TO_NATIVE(x) \
({ \
typeof(x) __x; \
- if (switch_endian) __endian(&(x), &(__x), sizeof(__x)); \
- else __x = x; \
+ __endian(&(x), &(__x), sizeof(__x)); \
__x; \
})
+#else /* endianness matches */
+
+#define TO_NATIVE(x) (x)
+
+#endif
+
+
#define ADD(str, sep, cond, field) \
do { \
strcat(str, sep); \
@@ -161,30 +199,80 @@ static int do_table(void *symval, unsigned long size,
return wrote;
}
-/* This is the best way of doing this without making a complete mess
- of the code. */
-#undef analyse_file
-#undef Elf_Ehdr
-#undef Elf_Shdr
-#undef Elf_Sym
-#undef EXTRA_SIZE
-#define analyse_file analyze_file32
-#define Elf_Ehdr Elf32_Ehdr
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define EXTRA_SIZE 0
-#include "file2alias_inc.c"
-#undef analyse_file
-#undef Elf_Ehdr
-#undef Elf_Shdr
-#undef Elf_Sym
-#undef EXTRA_SIZE
-#define analyse_file analyze_file64
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define EXTRA_SIZE 4
-#include "file2alias_inc.c"
+/* This contains the cookie-cutter code for ELF handling (32 v 64). */
+static void analyze_file(Elf_Ehdr *hdr,
+ unsigned int size,
+ const char *filename)
+{
+ unsigned int i, num_syms = 0;
+ Elf_Shdr *sechdrs;
+ Elf_Sym *syms = NULL;
+ char *secstrings, *strtab = NULL;
+ int first = 1;
+
+ if (size < sizeof(*hdr))
+ goto truncated;
+
+ sechdrs = (void *)hdr + TO_NATIVE(hdr->e_shoff);
+ hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
+ hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
+ hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
+ for (i = 0; i < hdr->e_shnum; i++) {
+ sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
+ sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
+ sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
+ sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
+ }
+
+ /* Find symbol table. */
+ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_offset > size)
+ goto truncated;
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ syms = (void *)hdr + sechdrs[i].sh_offset;
+ num_syms = sechdrs[i].sh_size / sizeof(syms[0]);
+ } else if (sechdrs[i].sh_type == SHT_STRTAB)
+ strtab = (void *)hdr + sechdrs[i].sh_offset;
+ }
+
+ if (!strtab || !syms) {
+ fprintf(stderr, "table2alias: %s no symtab?\n", filename);
+ abort();
+ }
+
+ for (i = 0; i < num_syms; i++) {
+ const char *symname;
+ void *symval;
+
+ syms[i].st_shndx = TO_NATIVE(syms[i].st_shndx);
+ syms[i].st_name = TO_NATIVE(syms[i].st_name);
+ syms[i].st_value = TO_NATIVE(syms[i].st_value);
+ syms[i].st_size = TO_NATIVE(syms[i].st_size);
+
+ if (!syms[i].st_shndx || syms[i].st_shndx >= hdr->e_shnum)
+ continue;
+
+ symname = strtab + syms[i].st_name;
+ symval = (void *)hdr
+ + sechdrs[syms[i].st_shndx].sh_offset
+ + syms[i].st_value;
+ if (sym_is(symname, "__mod_pci_device_table"))
+ do_table(symval, syms[i].st_size,
+ sizeof(struct pci_device_id),
+ do_pci_entry, filename, &first);
+ else if (sym_is(symname, "__mod_usb_device_table"))
+ do_table(symval, syms[i].st_size,
+ sizeof(struct usb_device_id),
+ do_usb_entry, filename, &first);
+ }
+ return;
+
+ truncated:
+ fprintf(stderr, "table2alias: %s is truncated.\n", filename);
+ abort();
+}
static void *grab_file(const char *filename, unsigned long *size)
{
@@ -215,45 +303,16 @@ int main(int argc, char *argv[])
{
void *file;
unsigned long size;
- int endian;
- union { short s; char c[2]; } endian_test;
-
- endian_test.s = 1;
- if (endian_test.c[1] == 1) endian = ELFDATA2MSB;
- else if (endian_test.c[0] == 1) endian = ELFDATA2LSB;
- else
- abort();
for (; argv[1]; argv++) {
file = grab_file(argv[1], &size);
if (!file) {
fprintf(stderr, "file2alias: opening %s: %s\n",
argv[1], strerror(errno));
- continue;
- }
-
- if (size < SELFMAG || memcmp(file, ELFMAG, SELFMAG) != 0)
- goto bad_elf;
-
- if (((unsigned char *)file)[EI_DATA] != endian)
- switch_endian = 1;
-
- switch (((unsigned char *)file)[EI_CLASS]) {
- case ELFCLASS32:
- analyze_file32(file, size, argv[1]);
- break;
- case ELFCLASS64:
- analyze_file64(file, size, argv[1]);
- break;
- default:
- goto bad_elf;
+ abort();
}
+ analyze_file(file, size, argv[1]);
munmap(file, size);
- continue;
-
- bad_elf:
- fprintf(stderr, "file2alias: %s is not elf\n", argv[1]);
- return 1;
}
return 0;
}
diff --git a/scripts/file2alias_inc.c b/scripts/file2alias_inc.c
deleted file mode 100644
index 3fcf52e0e3d4..000000000000
--- a/scripts/file2alias_inc.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* This contains the cookie-cutter code for ELF handling (32 v 64).
- Return true if anything output. */
-static void analyse_file(Elf_Ehdr *hdr,
- unsigned int size,
- const char *filename)
-{
- unsigned int i, num_syms = 0;
- Elf_Shdr *sechdrs;
- Elf_Sym *syms = NULL;
- char *secstrings, *strtab = NULL;
- int first = 1;
-
- if (size < sizeof(*hdr))
- goto truncated;
-
- sechdrs = (void *)hdr + TO_NATIVE(hdr->e_shoff);
- if (switch_endian) {
- hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
- hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
- hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
- for (i = 0; i < hdr->e_shnum; i++) {
- sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
- sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
- sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
- sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
- }
- }
-
- /* Find symbol table. */
- secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
-
- for (i = 1; i < hdr->e_shnum; i++) {
- if (sechdrs[i].sh_offset > size)
- goto truncated;
- if (sechdrs[i].sh_type == SHT_SYMTAB) {
- syms = (void *)hdr + sechdrs[i].sh_offset;
- num_syms = sechdrs[i].sh_size / sizeof(syms[0]);
- } else if (sechdrs[i].sh_type == SHT_STRTAB)
- strtab = (void *)hdr + sechdrs[i].sh_offset;
- }
-
- if (!strtab || !syms) {
- fprintf(stderr, "table2alias: %s no symtab?\n", filename);
- return;
- }
-
- for (i = 0; i < num_syms; i++) {
- const char *symname;
- void *symval;
-
- if (switch_endian) {
- syms[i].st_shndx = TO_NATIVE(syms[i].st_shndx);
- syms[i].st_name = TO_NATIVE(syms[i].st_name);
- syms[i].st_value = TO_NATIVE(syms[i].st_value);
- syms[i].st_size = TO_NATIVE(syms[i].st_size);
- }
-
- if (!syms[i].st_shndx || syms[i].st_shndx >= hdr->e_shnum)
- continue;
-
- symname = strtab + syms[i].st_name;
- symval = (void *)hdr
- + sechdrs[syms[i].st_shndx].sh_offset
- + syms[i].st_value;
- if (sym_is(symname, "__mod_pci_device_table"))
- do_table(symval, syms[i].st_size,
- sizeof(struct pci_device_id) + EXTRA_SIZE * 1,
- do_pci_entry, filename, &first);
- else if (sym_is(symname, "__mod_usb_device_table"))
- do_table(symval, syms[i].st_size,
- sizeof(struct usb_device_id) + EXTRA_SIZE * 1,
- do_usb_entry, filename, &first);
- }
- return;
-
- truncated:
- fprintf(stderr, "table2alias: %s is truncated.\n", filename);
- return;
-}
diff --git a/scripts/mk_elfconfig.c b/scripts/mk_elfconfig.c
new file mode 100644
index 000000000000..578785973bd7
--- /dev/null
+++ b/scripts/mk_elfconfig.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+
+int
+main(int argc, char **argv)
+{
+ unsigned char ei[EI_NIDENT];
+ union { short s; char c[2]; } endian_test;
+
+ if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
+ fprintf(stderr, "Error: input truncated\n");
+ return 1;
+ }
+ if (memcmp(ei, ELFMAG, SELFMAG) != 0) {
+ fprintf(stderr, "Error: not ELF\n");
+ return 1;
+ }
+ switch (ei[EI_CLASS]) {
+ case ELFCLASS32:
+ printf("#define KERNEL_ELFCLASS ELFCLASS32\n");
+ break;
+ case ELFCLASS64:
+ printf("#define KERNEL_ELFCLASS ELFCLASS64\n");
+ break;
+ default:
+ abort();
+ }
+ switch (ei[EI_DATA]) {
+ case ELFDATA2LSB:
+ printf("#define KERNEL_ELFDATA ELFDATA2LSB\n");
+ break;
+ case ELFDATA2MSB:
+ printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
+ break;
+ default:
+ abort();
+ }
+
+ if (sizeof(unsigned long) == 4) {
+ printf("#define HOST_ELFCLASS ELFCLASS32\n");
+ } else if (sizeof(unsigned long) == 8) {
+ printf("#define HOST_ELFCLASS ELFCLASS64\n");
+ }
+
+ endian_test.s = 0x0102;
+ if (memcmp(endian_test.c, "\x01\x02", 2) == 0)
+ printf("#define HOST_ELFDATA ELFDATA2MSB\n");
+ else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
+ printf("#define HOST_ELFDATA ELFDATA2LSB\n");
+ else
+ abort();
+
+ return 0;
+}
+