diff options
| author | Sam Ravnborg <sam@mars.ravnborg.org> | 2006-01-28 16:15:55 -0500 |
|---|---|---|
| committer | Sam Ravnborg <sam@mars.ravnborg.org> | 2006-02-19 03:51:18 -0500 |
| commit | 040fcc819a2e7783a570f4bdcdd1f2a7f5f06837 (patch) | |
| tree | 58a6cb2e7394c589c8ef49b308512c83af0c7087 /scripts | |
| parent | 5c3ead8c72788d36d34c9f1689fb529d1339b405 (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.modpost | 7 | ||||
| -rw-r--r-- | scripts/mod/modpost.c | 123 |
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 | |||
| 39 | include scripts/Kbuild.include | 39 | include scripts/Kbuild.include |
| 40 | include scripts/Makefile.lib | 40 | include scripts/Makefile.lib |
| 41 | 41 | ||
| 42 | symverfile := $(objtree)/Module.symvers | 42 | kernelsymfile := $(objtree)/Module.symvers |
| 43 | modulesymfile := $(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; | |||
| 20 | int have_vmlinux = 0; | 20 | int have_vmlinux = 0; |
| 21 | /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ | 21 | /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ |
| 22 | static int all_versions = 0; | 22 | static int all_versions = 0; |
| 23 | /* If we are modposting external module set to 1 */ | ||
| 24 | static int external_module = 0; | ||
| 23 | 25 | ||
| 24 | void fatal(const char *fmt, ...) | 26 | void 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 | ||
| 50 | static 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 | |||
| 48 | void *do_nofail(void *ptr, const char *expr) | 62 | void *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 */ |
| 138 | static void new_symbol(const char *name, struct module *module, | 155 | static 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 | ||
| 153 | static struct symbol *find_symbol(const char *name) | 166 | static 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 | **/ |
| 172 | static void add_exported_symbol(const char *name, struct module *module, | 185 | static 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 | |
| 197 | static 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 | ||
| 187 | void *grab_file(const char *filename, unsigned long *size) | 208 | void *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 | ||
| 391 | static 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 | mo | ||
