Skip to content
Snippets Groups Projects
modpost_external_module_updates_sles9.patch 8.96 KiB
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 <linux/module.h>\n");
 	buf_printf(b, "#include <linux/vermagic.h>\n");
@@ -676,8 +676,11 @@ read_supported(const char *fname)
 		; /* ignore error */
 }
 
+/* parse Module.symvers file. line format:
+ * 0x12345678<tab>symbol<tab>module[<tab>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);