aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSam Ravnborg <sam@mars.ravnborg.org>2006-01-28 16:15:55 -0500
committerSam Ravnborg <sam@mars.ravnborg.org>2006-02-19 03:51:18 -0500
commit040fcc819a2e7783a570f4bdcdd1f2a7f5f06837 (patch)
tree58a6cb2e7394c589c8ef49b308512c83af0c7087 /scripts
parent5c3ead8c72788d36d34c9f1689fb529d1339b405 (diff)
kbuild: improved modversioning support for external modules
With following patch a second option is enabled to obtain symbol information from a second external module when a external module is build. The recommended approach is to use a common kbuild file but that may be impractical in certain cases. With this patch one can copy over a Module.symvers from one external module to make symbols (and symbol versions) available for another external module. Updated documentation in Documentation/kbuild/modules.txt Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.modpost7
-rw-r--r--scripts/mod/modpost.c123
2 files changed, 78 insertions, 52 deletions
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index bf96a61d4b86..563e3c5bd8dd 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -39,7 +39,8 @@ include .config
39include scripts/Kbuild.include 39include scripts/Kbuild.include
40include scripts/Makefile.lib 40include scripts/Makefile.lib
41 41
42symverfile := $(objtree)/Module.symvers 42kernelsymfile := $(objtree)/Module.symvers
43modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers
43 44
44# Step 1), find all modules listed in $(MODVERDIR)/ 45# Step 1), find all modules listed in $(MODVERDIR)/
45__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) 46__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
@@ -54,7 +55,9 @@ quiet_cmd_modpost = MODPOST
54 cmd_modpost = scripts/mod/modpost \ 55 cmd_modpost = scripts/mod/modpost \
55 $(if $(CONFIG_MODVERSIONS),-m) \ 56 $(if $(CONFIG_MODVERSIONS),-m) \
56 $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ 57 $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \
57 $(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \ 58 $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \
59 $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \
60 $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
58 $(filter-out FORCE,$^) 61 $(filter-out FORCE,$^)
59 62
60.PHONY: __modpost 63.PHONY: __modpost
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 4a2f2e38d27f..976adf152db3 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -20,6 +20,8 @@ int modversions = 0;
20int have_vmlinux = 0; 20int have_vmlinux = 0;
21/* Is CONFIG_MODULE_SRCVERSION_ALL set? */ 21/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
22static int all_versions = 0; 22static int all_versions = 0;
23/* If we are modposting external module set to 1 */
24static int external_module = 0;
23 25
24void fatal(const char *fmt, ...) 26void fatal(const char *fmt, ...)
25{ 27{
@@ -45,6 +47,18 @@ void warn(const char *fmt, ...)
45 va_end(arglist); 47 va_end(arglist);
46} 48}
47 49
50static int is_vmlinux(const char *modname)
51{
52 const char *myname;
53
54 if ((myname = strrchr(modname, '/')))
55 myname++;
56 else
57 myname = modname;
58
59 return strcmp(myname, "vmlinux") == 0;
60}
61
48void *do_nofail(void *ptr, const char *expr) 62void *do_nofail(void *ptr, const char *expr)
49{ 63{
50 if (!ptr) { 64 if (!ptr) {
@@ -100,6 +114,9 @@ struct symbol {
100 unsigned int crc; 114 unsigned int crc;
101 int crc_valid; 115 int crc_valid;
102 unsigned int weak:1; 116 unsigned int weak:1;
117 unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
118 unsigned int kernel:1; /* 1 if symbol is from kernel
119 * (only for external modules) **/
103 char name[0]; 120 char name[0];
104}; 121};
105 122
@@ -135,8 +152,7 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak,
135} 152}
136 153
137/* For the hash of exported symbols */ 154/* For the hash of exported symbols */
138static void new_symbol(const char *name, struct module *module, 155static struct symbol *new_symbol(const char *name, struct module *module)
139 unsigned int *crc)
140{ 156{
141 unsigned int hash; 157 unsigned int hash;
142 struct symbol *new; 158 struct symbol *new;
@@ -144,10 +160,7 @@ static void new_symbol(const char *name, struct module *module,
144 hash = tdb_hash(name) % SYMBOL_HASH_SIZE; 160 hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
145 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); 161 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
146 new->module = module; 162 new->module = module;
147 if (crc) { 163 return new;
148 new->crc = *crc;
149 new->crc_valid = 1;
150 }
151} 164}
152 165
153static struct symbol *find_symbol(const char *name) 166static struct symbol *find_symbol(const char *name)
@@ -169,19 +182,27 @@ static struct symbol *find_symbol(const char *name)
169 * Add an exported symbol - it may have already been added without a 182 * Add an exported symbol - it may have already been added without a
170 * CRC, in this case just update the CRC 183 * CRC, in this case just update the CRC
171 **/ 184 **/
172static void add_exported_symbol(const char *name, struct module *module, 185static struct symbol *sym_add_exported(const char *name, struct module *mod)
173 unsigned int *crc)
174{ 186{
175 struct symbol *s = find_symbol(name); 187 struct symbol *s = find_symbol(name);
176 188
177 if (!s) { 189 if (!s)
178 new_symbol(name, module, crc); 190 s = new_symbol(name, mod);
179 return; 191
180 } 192 s->vmlinux = is_vmlinux(mod->name);
181 if (crc) { 193 s->kernel = 0;
182 s->crc = *crc; 194 return s;
183 s->crc_valid = 1; 195}
184 } 196
197static void sym_update_crc(const char *name, struct module *mod,
198 unsigned int crc)
199{
200 struct symbol *s = find_symbol(name);
201
202 if (!s)
203 s = new_symbol(name, mod);
204 s->crc = crc;
205 s->crc_valid = 1;
185} 206}
186 207
187void *grab_file(const char *filename, unsigned long *size) 208void *grab_file(const char *filename, unsigned long *size)
@@ -332,8 +353,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
332 /* CRC'd symbol */ 353 /* CRC'd symbol */
333 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { 354 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
334 crc = (unsigned int) sym->st_value; 355 crc = (unsigned int) sym->st_value;
335 add_exported_symbol(symname + strlen(CRC_PFX), 356 sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
336 mod, &crc);
337 } 357 }
338 break; 358 break;
339 case SHN_UNDEF: 359 case SHN_UNDEF:
@@ -377,8 +397,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
377 default: 397 default:
378 /* All exported symbols */ 398 /* All exported symbols */
379 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { 399 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
380 add_exported_symbol(symname + strlen(KSYMTAB_PFX), 400 sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
381 mod, NULL);
382 } 401 }
383 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) 402 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
384 mod->has_init = 1; 403 mod->has_init = 1;
@@ -388,18 +407,6 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
388 } 407 }
389} 408}
390 409
391static int is_vmlinux(const char *modname)
392{
393 const char *myname;
394
395 if ((myname = strrchr(modname, '/')))
396 myname++;
397 else
398 myname = modname;
399
400 return strcmp(myname, "vmlinux") == 0;
401}
402
403/** 410/**
404 * Parse tag=value strings from .modinfo section 411 * Parse tag=value strings from .modinfo section
405 **/ 412 **/
@@ -450,9 +457,7 @@ static void read_symbols(char *modname)
450 /* When there's no vmlinux, don't print warnings about 457 /* When there's no vmlinux, don't print warnings about
451 * unresolved symbols (since there'll be too many ;) */ 458 * unresolved symbols (since there'll be too many ;) */
452 if (is_vmlinux(modname)) { 459 if (is_vmlinux(modname)) {
453 unsigned int fake_crc = 0;
454 have_vmlinux = 1; 460 have_vmlinux = 1;
455 add_exported_symbol("struct_module", mod, &fake_crc);
456 mod->skip = 1; 461 mod->skip = 1;
457 } 462 }
458 463
@@ -665,7 +670,7 @@ static void write_if_changed(struct buffer *b, const char *fname)
665 fclose(file); 670 fclose(file);
666} 671}
667 672
668static void read_dump(const char *fname) 673static void read_dump(const char *fname, unsigned int kernel)
669{ 674{
670 unsigned long size, pos = 0; 675 unsigned long size, pos = 0;
671 void *file = grab_file(fname, &size); 676 void *file = grab_file(fname, &size);
@@ -679,6 +684,7 @@ static void read_dump(const char *fname)
679 char *symname, *modname, *d; 684 char *symname, *modname, *d;
680 unsigned int crc; 685 unsigned int crc;
681 struct module *mod; 686 struct module *mod;
687 struct symbol *s;
682 688
683 if (!(symname = strchr(line, '\t'))) 689 if (!(symname = strchr(line, '\t')))
684 goto fail; 690 goto fail;
@@ -699,13 +705,28 @@ static void read_dump(const char *fname)
699 mod = new_module(NOFAIL(strdup(modname))); 705 mod = new_module(NOFAIL(strdup(modname)));
700 mod->skip = 1; 706 mod->skip = 1;
701 } 707 }
702 add_exported_symbol(symname, mod, &crc); 708 s = sym_add_exported(symname, mod);
709 s->kernel = kernel;
710 sym_update_crc(symname, mod, crc);
703 } 711 }
704 return; 712 return;
705fail: 713fail:
706 fatal("parse error in symbol dump file\n"); 714 fatal("parse error in symbol dump file\n");
707} 715}
708 716
717/* For normal builds always dump all symbols.
718 * For external modules only dump symbols
719 * that are not read from kernel Module.symvers.
720 **/
721static int dump_sym(struct symbol *sym)
722{
723 if (!external_module)
724 return 1;
725 if (sym->vmlinux || sym->kernel)
726 return 0;
727 return 1;
728}
729
709static void write_dump(const char *fname) 730static void write_dump(const char *fname)
710{ 731{
711 struct buffer buf = { }; 732 struct buffer buf = { };
@@ -715,15 +736,10 @@ static void write_dump(const char *fname)
715 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { 736 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
716 symbol = symbolhash[n]; 737 symbol = symbolhash[n];
717 while (symbol) { 738 while (symbol) {
718 symbol = symbol->next; 739 if (dump_sym(symbol))
719 } 740 buf_printf(&buf, "0x%08x\t%s\t%s\n",
720 } 741 symbol->crc, symbol->name,
721 742 symbol->module->name);
722 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
723 symbol = symbolhash[n];
724 while (symbol) {
725 buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc,
726 symbol->name, symbol->module->name);
727 symbol = symbol->next; 743 symbol = symbol->next;
728 } 744 }
729 } 745 }
@@ -735,13 +751,18 @@ int main(int argc, char **argv)
735 struct module *mod; 751 struct module *mod;
736 struct buffer buf = { }; 752 struct buffer buf = { };
737 char fname[SZ]; 753 char fname[SZ];
738 char *dump_read = NULL, *dump_write = NULL; 754 char *kernel_read = NULL, *module_read = NULL;
755 char *dump_write = NULL;
739 int opt; 756 int opt;
740 757
741 while ((opt = getopt(argc, argv, "i:mo:a")) != -1) { 758 while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
742 switch(opt) { 759 switch(opt) {
743 case 'i': 760 case 'i':
744 dump_read = optarg; 761 kernel_read = optarg;
762 break;
763 case 'I':
764 module_read = optarg;
765 external_module = 1;
745 break; 766 break;
746 case 'm': 767 case 'm':
747 modversions = 1; 768 modversions = 1;
@@ -757,8 +778,10 @@ int main(int argc, char **argv)
757 } 778 }
758 } 779 }
759 780
760 if (dump_read) 781 if (kernel_read)
761 read_dump(dump_read); 782 read_dump(kernel_read, 1);
783 if (module_read)
784 read_dump(module_read, 0);
762 785
763 while (optind < argc) { 786 while (optind < argc) {
764 read_symbols(argv[optind++]); 787 read_symbols(argv[optind++]);