summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile10
-rw-r--r--scripts/Makefile.modver19
-rw-r--r--scripts/file2alias.c236
-rw-r--r--scripts/modpost.c275
-rw-r--r--scripts/modpost.h86
5 files changed, 324 insertions, 302 deletions
diff --git a/scripts/Makefile b/scripts/Makefile
index 59bdaae2e5b7..eeed3759799e 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -9,9 +9,11 @@
# conmakehash: Create arrays for initializing the kernel console tables
host-progs := fixdep split-include conmakehash docproc kallsyms modpost \
- file2alias mk_elfconfig
+ mk_elfconfig
build-targets := $(host-progs) empty.o
+modpost-objs := modpost.o file2alias.o
+
# Let clean descend into subdirs
subdir- := lxdialog kconfig
@@ -20,12 +22,12 @@ $(addprefix $(obj)/,$(filter-out fixdep,$(host-progs))): $(obj)/fixdep
# dependencies on generated files need to be listed explicitly
-$(obj)/file2alias: $(obj)/elfconfig.h
+$(obj)/modpost.o $(obj)/file2alias.o: $(obj)/elfconfig.h
-quiet_cmd_elfconfig = MKTARGET $@
+quiet_cmd_elfconfig = MKELF $@
cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
$(call if_changed,elfconfig)
-targets += $(obj)/target.h
+targets += $(obj)/elfconfig.h
diff --git a/scripts/Makefile.modver b/scripts/Makefile.modver
index 6d1a3cb32232..e89ed0955d50 100644
--- a/scripts/Makefile.modver
+++ b/scripts/Makefile.modver
@@ -27,7 +27,7 @@ quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = $(LD) $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \
$(filter-out FORCE,$^)
-$(modules): %.ko :%.o %.ver.o $(if CONFIG_HOTPLUG,%.aliases.o) FORCE
+$(modules): %.ko :%.o %.ver.o FORCE
$(call if_changed,ld_ko_o)
targets += $(modules)
@@ -45,21 +45,6 @@ $(modules:.ko=.ver.o): %.ver.o: %.ver.c include/linux/compile.h FORCE
targets += $(modules:.ko=.ver.o)
-$(modules:.ko=.aliases.o): %.aliases.o: %.aliases.c FORCE
- $(call if_changed,cc_o_c)
-
-targets += $(modules:.ko=.aliases.o)
-
-# Generate aliases
-
-quiet_cmd_file2alias = ALIAS $@
- cmd_file2alias = scripts/file2alias $< > $@
-
-$(modules:.ko=.aliases.c): %.aliases.c: %.o FORCE
- $(call if_changed,file2alias)
-
-targets += $(modules:.ko=.aliases.c)
-
# All the .ver.c files are generated using the helper "modpost"
.PHONY: __modpost
@@ -69,7 +54,7 @@ $(modules:.ko=.ver.c): __modpost ;
# Extract all checksums for all exported symbols
quiet_cmd_modpost = MODPOST
- cmd_modpost = scripts/modpost $(NM) $^
+ cmd_modpost = scripts/modpost $^
__modpost: $(wildcard vmlinux) $(modules:.ko=.o)
$(call if_changed,modpost)
diff --git a/scripts/file2alias.c b/scripts/file2alias.c
index b638f80de910..cdb1e4c6a350 100644
--- a/scripts/file2alias.c
+++ b/scripts/file2alias.c
@@ -1,23 +1,16 @@
/* Simple code to turn various tables in an ELF file into alias definitions.
- This deals with kernel datastructures where they should be
- dealt with: in the kernel source.
- (C) 2002 Rusty Russell IBM Corporation.
-*/
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <elf.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdint.h>
-#include <endian.h>
-
-#include "elfconfig.h"
+ * This deals with kernel datastructures where they should be
+ * dealt with: in the kernel source.
+ *
+ * Copyright 2002-2003 Rusty Russell, IBM Corporation
+ * 2003 Kai Germaschewski
+ *
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "modpost.h"
/* We use the ELF typedefs, since we can't rely on stdint.h being present. */
@@ -36,45 +29,6 @@ typedef unsigned char __u8;
* we handle those differences explicitly below */
#include "../include/linux/mod_devicetable.h"
-#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)
-{
- 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; \
- __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); \
@@ -145,7 +99,7 @@ static int do_pci_entry(const char *filename,
ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
if (id->class_mask != 0 && id->class_mask != ~0) {
fprintf(stderr,
- "file2alias: Can't handle class_mask in %s:%04X\n",
+ "*** Warning: Can't handle class_mask in %s:%04X\n",
filename, id->class_mask);
return 0;
}
@@ -164,155 +118,61 @@ static inline int sym_is(const char *symbol, const char *name)
return match[strlen(symbol)] == '\0';
}
-/* Returns 1 if we output anything. */
-static int do_table(void *symval, unsigned long size,
- unsigned long id_size,
- void *function,
- const char *filename, int *first)
+static void do_table(void *symval, unsigned long size,
+ unsigned long id_size,
+ void *function,
+ struct module *mod)
{
unsigned int i;
char alias[500];
int (*do_entry)(const char *, void *entry, char *alias) = function;
- int wrote = 0;
if (size % id_size || size < id_size) {
- fprintf(stderr, "WARNING: %s ids %lu bad size (each on %lu)\n",
- filename, size, id_size);
- return 0;
+ fprintf(stderr, "*** Warning: %s ids %lu bad size "
+ "(each on %lu)\n", mod->name, size, id_size);
}
/* Leave last one: it's the terminator. */
size -= id_size;
for (i = 0; i < size; i += id_size) {
- if (do_entry(filename, symval+i, alias)) {
+ if (do_entry(mod->name, symval+i, alias)) {
/* Always end in a wildcard, for future extension */
if (alias[strlen(alias)-1] != '*')
strcat(alias, "*");
- if (*first) {
- printf("#include <linux/module.h>\n\n");
- *first = 0;
- }
- printf("MODULE_ALIAS(\"%s\");\n", alias);
- wrote = 1;
+ buf_printf(&mod->dev_table_buf,
+ "MODULE_ALIAS(\"%s\");\n", alias);
}
}
- return wrote;
}
-/* 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)
+/* Create MODULE_ALIAS() statements.
+ * At this time, we cannot write the actual output C source yet,
+ * so we write into the mod->dev_table_buf buffer. */
+void handle_moddevtable(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname)
{
- 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();
+ void *symval;
+
+ /* We're looking for a section relative symbol */
+ if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
+ return;
+
+ symval = (void *)info->hdr
+ + info->sechdrs[sym->st_shndx].sh_offset
+ + sym->st_value;
+
+ if (sym_is(symname, "__mod_pci_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct pci_device_id),
+ do_pci_entry, mod);
+ else if (sym_is(symname, "__mod_usb_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct usb_device_id),
+ do_usb_entry, mod);
}
-static void *grab_file(const char *filename, unsigned long *size)
+/* Now add out buffered information to the generated C source */
+void add_moddevtable(struct buffer *buf, struct module *mod)
{
- struct stat st;
- void *map;
- int fd;
-
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return NULL;
- if (fstat(fd, &st) != 0) {
- close(fd);
- return NULL;
- }
- *size = st.st_size;
- map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (mmap == MAP_FAILED) {
- close(fd);
- return NULL;
- }
- close(fd);
- return map;
-}
-
-/* Look through files for __mod_*_device_table: emit alias definitions
- for compiling in. */
-int main(int argc, char *argv[])
-{
- void *file;
- unsigned long size;
-
- for (; argv[1]; argv++) {
- file = grab_file(argv[1], &size);
- if (!file) {
- fprintf(stderr, "file2alias: opening %s: %s\n",
- argv[1], strerror(errno));
- abort();
- }
- analyze_file(file, size, argv[1]);
- munmap(file, size);
- }
- return 0;
+ buf_printf(buf, "\n");
+ buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
+ free(mod->dev_table_buf.p);
}
diff --git a/scripts/modpost.c b/scripts/modpost.c
index fb8a54414b87..b10352e6a928 100644
--- a/scripts/modpost.c
+++ b/scripts/modpost.c
@@ -1,38 +1,22 @@
/* Postprocess module symbol versions
*
* Copyright 2003 Kai Germaschewski
- * 2002 Rusty Russell IBM Corporation
+ * 2002-2003 Rusty Russell, IBM Corporation
*
- * Based in part on module-init-tools/depmod.c
+ * Based in part on module-init-tools/depmod.c,file2alias
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
- * Usage: modpost $(NM) vmlinux module1.o module2.o ...
+ * Usage: modpost vmlinux module1.o module2.o ...
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/* nm command */
-const char *nm;
+#include "modpost.h"
/* Are we using CONFIG_MODVERSIONS? */
int modversions = 0;
void
-usage(void)
-{
- fprintf(stderr, "Usage: modpost $(NM) vmlinux module1.o module2.o\n");
- exit(1);
-}
-
-void
fatal(const char *fmt, ...)
{
va_list arglist;
@@ -71,15 +55,30 @@ void *do_nofail(void *ptr, const char *file, int line, const char *expr)
/* A list of all modules we processed */
-struct module {
- struct module *next;
- const char *name;
- struct symbol *unres;
- int seen;
-};
-
static struct module *modules;
+struct module *
+new_module(char *modname)
+{
+ struct module *mod;
+ char *p;
+
+ /* strip trailing .o */
+ p = strstr(modname, ".o");
+ if (p)
+ *p = 0;
+
+ mod = NOFAIL(malloc(sizeof(*mod)));
+ memset(mod, 0, sizeof(*mod));
+ mod->name = modname;
+
+ /* add to list */
+ mod->next = modules;
+ modules = mod;
+
+ return mod;
+}
+
/* A hash of all exported symbols,
* struct symbol is also used for lists of unresolved symbols */
@@ -159,7 +158,7 @@ find_symbol(const char *name)
/* Add an exported symbol - it may have already been added without a
* CRC, in this case just update the CRC */
void
-add_symbol(const char *name, struct module *module, unsigned int *crc)
+add_exported_symbol(const char *name, struct module *module, unsigned int *crc)
{
struct symbol *s = find_symbol(name);
@@ -173,74 +172,162 @@ add_symbol(const char *name, struct module *module, unsigned int *crc)
}
}
-#define SZ 500
+void *
+grab_file(const char *filename, unsigned long *size)
+{
+ struct stat st;
+ void *map;
+ int fd;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ abort();
+ }
+ if (fstat(fd, &st) != 0) {
+ perror(filename);
+ abort();
+ }
+
+ *size = st.st_size;
+ map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (mmap == MAP_FAILED) {
+ perror(filename);
+ abort();
+ }
+ close(fd);
+ return map;
+}
void
-read_symbols(char *modname)
+parse_elf(struct elf_info *info, const char *filename)
{
- struct module *mod;
- struct symbol *s;
- char buf[SZ], sym[SZ], *p;
- FILE *pipe;
- unsigned int crc;
- int rc;
+ unsigned int i;
+ Elf_Ehdr *hdr = info->hdr;
+ Elf_Shdr *sechdrs;
+ Elf_Sym *sym;
+
+ hdr = grab_file(filename, &info->size);
+ info->hdr = hdr;
+ if (info->size < sizeof(*hdr))
+ goto truncated;
+
+ /* Fix endianness in ELF header */
+ hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
+ hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
+ hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
+ sechdrs = (void *)hdr + hdr->e_shoff;
+ info->sechdrs = sechdrs;
+
+ /* Fix endianness in section headers */
+ 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. */
+ for (i = 1; i < hdr->e_shnum; i++) {
+ if (sechdrs[i].sh_offset > info->size)
+ goto truncated;
+ if (sechdrs[i].sh_type != SHT_SYMTAB)
+ continue;
- /* read nm output */
- snprintf(buf, SZ, "%s --no-sort %s", nm, modname);
- pipe = NOFAIL(popen(buf, "r"));
+ info->symtab_start = (void *)hdr + sechdrs[i].sh_offset;
+ info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset
+ + sechdrs[i].sh_size;
+ info->strtab = (void *)hdr +
+ sechdrs[sechdrs[i].sh_link].sh_offset;
+ }
+ if (!info->symtab_start) {
+ fprintf(stderr, "modpost: %s no symtab?\n", filename);
+ abort();
+ }
+ /* Fix endianness in symbols */
+ for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
+ sym->st_shndx = TO_NATIVE(sym->st_shndx);
+ sym->st_name = TO_NATIVE(sym->st_name);
+ sym->st_value = TO_NATIVE(sym->st_value);
+ sym->st_size = TO_NATIVE(sym->st_size);
+ }
+ return;
- /* strip trailing .o */
- p = strstr(modname, ".o");
- if (p)
- *p = 0;
+ truncated:
+ fprintf(stderr, "modpost: %s is truncated.\n", filename);
+ abort();
+}
- mod = NOFAIL(malloc(sizeof(*mod)));
- mod->name = modname;
- /* add to list */
- mod->next = modules;
- modules = mod;
-
- while (fgets(buf, SZ, pipe)) {
- /* actual CRCs */
- rc = sscanf(buf, "%x A __crc_%s\n", &crc, sym);
- if (rc == 2) {
- add_symbol(sym, mod, &crc);
+void
+parse_elf_finish(struct elf_info *info)
+{
+ munmap(info->hdr, info->size);
+}
+
+void
+handle_modversions(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname)
+{
+ struct symbol *s;
+
+ switch (sym->st_shndx) {
+ case SHN_COMMON:
+ fprintf(stderr, "*** Warning: \"%s\" [%s] is COMMON symbol\n",
+ symname, mod->name);
+ break;
+ case SHN_ABS:
+ /* CRC'd symbol */
+ if (memcmp(symname, "__crc_", 6) == 0) {
+ add_exported_symbol(symname+6, mod, &sym->st_value);
modversions = 1;
- continue;
}
-
- /* all exported symbols */
- rc = sscanf(buf, "%x r __ksymtab_%s", &crc, sym);
- if (rc == 2) {
- add_symbol(sym, mod, NULL);
- continue;
+ break;
+ case SHN_UNDEF:
+ /* undefined symbol */
+ if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
+ break;
+
+ s = alloc_symbol(symname);
+ /* add to list */
+ s->next = mod->unres;
+ mod->unres = s;
+ break;
+ default:
+ /* All exported symbols */
+ if (memcmp(symname, "__ksymtab_", 10) == 0) {
+ add_exported_symbol(symname+10, mod, NULL);
}
+ break;
+ }
+}
- /* all unresolved symbols */
- rc = sscanf(buf, " U %s\n", sym);
- if (rc == 1) {
- s = alloc_symbol(sym);
- /* add to list */
- s->next = mod->unres;
- mod->unres = s;
- continue;
- }
- };
- pclose(pipe);
+void
+read_symbols(char *modname)
+{
+ const char *symname;
+ struct module *mod;
+ struct elf_info info = { };
+ Elf_Sym *sym;
+
+ parse_elf(&info, modname);
+
+ mod = new_module(modname);
+
+ for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
+ symname = info.strtab + sym->st_name;
+
+ handle_modversions(mod, &info, sym, symname);
+ handle_moddevtable(mod, &info, sym, symname);
+ }
+ parse_elf_finish(&info);
}
+#define SZ 500
+
/* We first write the generated file into memory using the
* following helper, then compare to the file on disk and
* only update the later if anything changed */
-struct buffer {
- char *p;
- int pos;
- int size;
-};
-
-void
-__attribute__((format(printf, 2, 3)))
+void __attribute__((format(printf, 2, 3)))
buf_printf(struct buffer *buf, const char *fmt, ...)
{
char tmp[SZ];
@@ -250,11 +337,7 @@ buf_printf(struct buffer *buf, const char *fmt, ...)
va_start(ap, fmt);
len = vsnprintf(tmp, SZ, fmt, ap);
if (buf->size - buf->pos < len + 1) {
- if (buf->size == 0)
- buf->size = 1024;
- else
- buf->size *= 2;
-
+ buf->size += 128;
buf->p = realloc(buf->p, buf->size);
}
strncpy(buf->p + buf->pos, tmp, len + 1);
@@ -262,6 +345,17 @@ buf_printf(struct buffer *buf, const char *fmt, ...)
va_end(ap);
}
+void
+buf_write(struct buffer *buf, const char *s, int len)
+{
+ if (buf->size - buf->pos < len) {
+ buf->size += len;
+ buf->p = realloc(buf->p, buf->size);
+ }
+ strncpy(buf->p + buf->pos, s, len);
+ buf->pos += len;
+}
+
/* Header for the generated file */
void
@@ -399,18 +493,12 @@ write_if_changed(struct buffer *b, const char *fname)
int
main(int argc, char **argv)
{
- int i;
struct module *mod;
struct buffer buf = { };
char fname[SZ];
- if (argc < 3)
- usage();
-
- nm = argv[1];
-
- for (i = 2; i < argc; i++) {
- read_symbols(argv[i]);
+ for (; argv[1]; argv++) {
+ read_symbols(argv[1]);
}
for (mod = modules; mod; mod = mod->next) {
@@ -422,6 +510,7 @@ main(int argc, char **argv)
add_header(&buf);
add_versions(&buf, mod);
add_depends(&buf, mod, modules);
+ add_moddevtable(&buf, mod);
sprintf(fname, "%s.ver.c", mod->name);
write_if_changed(&buf, fname);
diff --git a/scripts/modpost.h b/scripts/modpost.h
new file mode 100644
index 000000000000..1a5c8e829cc8
--- /dev/null
+++ b/scripts/modpost.h
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+
+#include "elfconfig.h"
+
+#if KERNEL_ELFCLASS == ELFCLASS32
+
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define ELF_ST_BIND ELF32_ST_BIND
+
+#else
+
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define ELF_ST_BIND ELF64_ST_BIND
+
+#endif
+
+#if KERNEL_ELFDATA != HOST_ELFDATA
+
+static 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; \
+ __endian(&(x), &(__x), sizeof(__x)); \
+ __x; \
+})
+
+#else /* endianness matches */
+
+#define TO_NATIVE(x) (x)
+
+#endif
+
+struct buffer {
+ char *p;
+ int pos;
+ int size;
+};
+
+void __attribute__((format(printf, 2, 3)))
+buf_printf(struct buffer *buf, const char *fmt, ...);
+
+void
+buf_write(struct buffer *buf, const char *s, int len);
+
+struct module {
+ struct module *next;
+ const char *name;
+ struct symbol *unres;
+ int seen;
+ struct buffer dev_table_buf;
+};
+
+struct elf_info {
+ unsigned long size;
+ Elf_Ehdr *hdr;
+ Elf_Shdr *sechdrs;
+ Elf_Sym *symtab_start;
+ Elf_Sym *symtab_stop;
+ const char *strtab;
+};
+
+void handle_moddevtable(struct module *mod, struct elf_info *info,
+ Elf_Sym *sym, const char *symname);
+
+void add_moddevtable(struct buffer *buf, struct module *mod);