This patch updates the SLES 9 module build system to properly support dependencies between external modules, similarly to the way they are supported in newer kernels. Index: linux-2.6.5-7.286/scripts/Makefile.modpost =================================================================== --- linux-2.6.5-7.286.orig/scripts/Makefile.modpost +++ linux-2.6.5-7.286/scripts/Makefile.modpost @@ -38,7 +38,8 @@ _modpost: __modpost include .config include scripts/Makefile.lib -symverfile := $(objtree)/Module.symvers +kernelsymfile := $(objtree)/Module.symvers +modulesymfile := $(KBUILD_EXTMOD)/Module.symvers # Step 1), find all modules listed in $(MODVERDIR)/ __modules := $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod)) @@ -51,7 +52,9 @@ _modpost: $(modules) # Includes step 3,4 quiet_cmd_modpost = MODPOST cmd_modpost = scripts/modpost \ - $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \ + $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ + $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ + $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ -s $(firstword $(wildcard $(dir $(MODVERDIR))/Module.supported \ $(objtree)/Module.supported /dev/null)) \ $(filter-out FORCE,$^) Index: linux-2.6.5-7.286/scripts/modpost.c =================================================================== --- linux-2.6.5-7.286.orig/scripts/modpost.c +++ linux-2.6.5-7.286/scripts/modpost.c @@ -1,7 +1,8 @@ /* Postprocess module symbol versions * * Copyright 2003 Kai Germaschewski - * 2002-2003 Rusty Russell, IBM Corporation + * 2002-2004 Rusty Russell, IBM Corporation + * Copyright 2006 Sam Ravnborg * * Based in part on module-init-tools/depmod.c,file2alias * @@ -18,6 +19,8 @@ int modversions = 0; /* Warn about undefined symbols? (do so if we have vmlinux) */ int have_vmlinux = 0; +/* If we are modposting external module set to 1 */ +static int external_module = 0; void fatal(const char *fmt, ...) @@ -45,6 +48,19 @@ warn(const char *fmt, ...) va_end(arglist); } +int +is_vmlinux(const char *modname) +{ + const char *myname; + + if ((myname = strrchr(modname, '/'))) + myname++; + else + myname = modname; + + return strcmp(myname, "vmlinux") == 0; +} + void *do_nofail(void *ptr, const char *expr) { if (!ptr) { @@ -101,6 +117,9 @@ struct symbol { struct module *module; unsigned int crc; int crc_valid; + unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ + unsigned int kernel:1; /* 1 if symbol is from kernel + * (only for external modules) **/ char name[0]; }; @@ -135,8 +154,8 @@ alloc_symbol(const char *name, struct sy /* For the hash of exported symbols */ -void -new_symbol(const char *name, struct module *module, unsigned int *crc) +static struct symbol * +new_symbol(const char *name, struct module *module) { unsigned int hash; struct symbol *new; @@ -144,10 +163,7 @@ new_symbol(const char *name, struct modu hash = tdb_hash(name) % SYMBOL_HASH_SIZE; new = symbolhash[hash] = alloc_symbol(name, symbolhash[hash]); new->module = module; - if (crc) { - new->crc = *crc; - new->crc_valid = 1; - } + return new; } struct symbol * @@ -168,19 +184,28 @@ 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_exported_symbol(const char *name, struct module *module, unsigned int *crc) +static struct symbol * +sym_add_exported(const char *name, struct module *mod) { struct symbol *s = find_symbol(name); if (!s) { - new_symbol(name, module, crc); - return; - } - if (crc) { - s->crc = *crc; - s->crc_valid = 1; + s = new_symbol(name, mod); } + s->vmlinux = is_vmlinux(mod->name); + s->kernel = 0; + return s; +} + +static void +sym_update_crc(const char *name, struct module *mod, unsigned int crc) +{ + struct symbol *s = find_symbol(name); + + if (!s) + s = new_symbol(name, mod); + s->crc = crc; + s->crc_valid = 1; } void * @@ -339,8 +364,7 @@ handle_modversions(struct module *mod, s /* CRC'd symbol */ if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { crc = (unsigned int) sym->st_value; - add_exported_symbol(symname + strlen(CRC_PFX), - mod, &crc); + sym_update_crc(symname + strlen(CRC_PFX), mod, crc); modversions = 1; } break; @@ -372,26 +396,12 @@ handle_modversions(struct module *mod, s default: /* All exported symbols */ if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { - add_exported_symbol(symname + strlen(KSYMTAB_PFX), - mod, NULL); + sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); } break; } } -int -is_vmlinux(const char *modname) -{ - const char *myname; - - if ((myname = strrchr(modname, '/'))) - myname++; - else - myname = modname; - - return strcmp(myname, "vmlinux") == 0; -} - static struct { void *file; unsigned long size; @@ -451,12 +461,7 @@ read_symbols(char *modname) /* When there's no vmlinux, don't print warnings about * unresolved symbols (since there'll be too many ;) */ if (is_vmlinux(modname)) { - unsigned int fake_crc = 0; have_vmlinux = 1; - /* May not have this if !CONFIG_MODULE_UNLOAD: fake it. - If it appears, we'll get the real CRC. */ - add_exported_symbol("cleanup_module", mod, &fake_crc); - add_exported_symbol("struct_module", mod, &fake_crc); mod->skip = 1; } @@ -499,12 +504,7 @@ buf_printf(struct buffer *buf, const cha va_start(ap, fmt); len = vsnprintf(tmp, SZ, fmt, ap); - if (buf->size - buf->pos < len + 1) { - buf->size += 128; - buf->p = realloc(buf->p, buf->size); - } - strncpy(buf->p + buf->pos, tmp, len + 1); - buf->pos += len; + buf_write(buf, tmp, len); va_end(ap); } @@ -512,7 +512,7 @@ void buf_write(struct buffer *buf, const char *s, int len) { if (buf->size - buf->pos < len) { - buf->size += len; + buf->size += len + SZ; buf->p = realloc(buf->p, buf->size); } strncpy(buf->p + buf->pos, s, len); @@ -522,7 +522,7 @@ buf_write(struct buffer *buf, const char /* Header for the generated file */ void -add_header(struct buffer *b) +add_header(struct buffer *b, struct module *mod) { buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); @@ -676,8 +676,11 @@ read_supported(const char *fname) ; /* ignore error */ } +/* parse Module.symvers file. line format: + * 0x12345678symbolmodule[something] + **/ void -read_dump(const char *fname) +read_dump(const char *fname, unsigned int kernel) { unsigned long size, pos = 0; void *file = grab_file(fname, &size); @@ -691,6 +694,7 @@ read_dump(const char *fname) char *symname, *modname, *d; unsigned int crc; struct module *mod; + struct symbol *s; if (!(symname = strchr(line, '\t'))) goto fail; @@ -712,13 +716,29 @@ read_dump(const char *fname) mod = new_module(NOFAIL(strdup(modname))); mod->skip = 1; } - add_exported_symbol(symname, mod, &crc); + s = sym_add_exported(symname, mod); + s->kernel = kernel; + sym_update_crc(symname, mod, crc); } return; fail: fatal("parse error in symbol dump file\n"); } +/* For normal builds always dump all symbols. + * For external modules only dump symbols + * that are not read from kernel Module.symvers. + **/ +static int +dump_sym(struct symbol *sym) +{ + if (!external_module) + return 1; + if (sym->vmlinux || sym->kernel) + return 0; + return 1; +} + void write_dump(const char *fname) { @@ -729,15 +749,10 @@ write_dump(const char *fname) for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n]; while (symbol) { - symbol = symbol->next; - } - } - - for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { - symbol = symbolhash[n]; - while (symbol) { - buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc, - symbol->name, symbol->module->name); + if (dump_sym(symbol)) + buf_printf(&buf, "0x%08x\t%s\t%s\n", + symbol->crc, symbol->name, + symbol->module->name); symbol = symbol->next; } } @@ -750,14 +765,19 @@ main(int argc, char **argv) struct module *mod; struct buffer buf = { }; char fname[SZ]; - char *dump_read = NULL, *dump_write = NULL; + char *kernel_read = NULL, *module_read = NULL; + char *dump_write = NULL; char *supp = NULL; int opt; - while ((opt = getopt(argc, argv, "i:o:s:")) != -1) { + while ((opt = getopt(argc, argv, "i:I:o:s:")) != -1) { switch(opt) { case 'i': - dump_read = optarg; + kernel_read = optarg; + break; + case 'I': + module_read = optarg; + external_module = 1; break; case 'o': dump_write = optarg; @@ -773,8 +793,10 @@ main(int argc, char **argv) if (supp) read_supported(supp); - if (dump_read) - read_dump(dump_read); + if (kernel_read) + read_dump(kernel_read, 1); + if (module_read) + read_dump(module_read, 0); while (optind < argc) { read_symbols(argv[optind++]); @@ -786,7 +808,7 @@ main(int argc, char **argv) buf.pos = 0; - add_header(&buf); + add_header(&buf, mod); add_supported_flag(&buf, mod); add_versions(&buf, mod); add_depends(&buf, mod, modules);