diff options
| author | Ram Pai <linuxram@us.ibm.com> | 2006-06-09 01:12:53 -0400 |
|---|---|---|
| committer | Sam Ravnborg <sam@mars.ravnborg.org> | 2006-06-09 14:33:10 -0400 |
| commit | bd5cbcedf446e2f37cf2a37f533a7e1d7dff9312 (patch) | |
| tree | 97cf8ea555684697b50a9444d75c33d28af0f0f4 /scripts/mod | |
| parent | 031ecc6de7d17752c57720a118a37e97a8454872 (diff) | |
kbuild: export-type enhancement to modpost.c
This patch provides the ability to identify the export-type of each
exported symbols in Module.symvers.
NOTE: It updates the Module.symvers file with the additional
information as shown below.
0x0f8b92af platform_device_add_resources vmlinux EXPORT_SYMBOL_GPL
0xcf7efb2a ethtool_op_set_tx_csum vmlinux EXPORT_SYMBOL
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Avantika Mathur <mathur@us.ibm.com>
Signed-off-by: Valdis Kletnieks <valdis.kletnieks@vt.edu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/modpost.c | 93 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 3 |
2 files changed, 80 insertions, 16 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a70f5ddb705c..ba2e4fc2af20 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -22,6 +22,8 @@ int have_vmlinux = 0; | |||
| 22 | static int all_versions = 0; | 22 | static int all_versions = 0; |
| 23 | /* If we are modposting external module set to 1 */ | 23 | /* If we are modposting external module set to 1 */ |
| 24 | static int external_module = 0; | 24 | static int external_module = 0; |
| 25 | /* How a symbol is exported */ | ||
| 26 | enum export {export_plain, export_gpl, export_gpl_future, export_unknown}; | ||
| 25 | 27 | ||
| 26 | void fatal(const char *fmt, ...) | 28 | void fatal(const char *fmt, ...) |
| 27 | { | 29 | { |
| @@ -118,6 +120,7 @@ struct symbol { | |||
| 118 | unsigned int kernel:1; /* 1 if symbol is from kernel | 120 | unsigned int kernel:1; /* 1 if symbol is from kernel |
| 119 | * (only for external modules) **/ | 121 | * (only for external modules) **/ |
| 120 | unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ | 122 | unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ |
| 123 | enum export export; /* Type of export */ | ||
| 121 | char name[0]; | 124 | char name[0]; |
| 122 | }; | 125 | }; |
| 123 | 126 | ||
| @@ -153,7 +156,8 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak, | |||
| 153 | } | 156 | } |
| 154 | 157 | ||
| 155 | /* For the hash of exported symbols */ | 158 | /* For the hash of exported symbols */ |
| 156 | static struct symbol *new_symbol(const char *name, struct module *module) | 159 | static struct symbol *new_symbol(const char *name, struct module *module, |
| 160 | enum export export) | ||
| 157 | { | 161 | { |
| 158 | unsigned int hash; | 162 | unsigned int hash; |
| 159 | struct symbol *new; | 163 | struct symbol *new; |
| @@ -161,6 +165,7 @@ static struct symbol *new_symbol(const char *name, struct module *module) | |||
| 161 | hash = tdb_hash(name) % SYMBOL_HASH_SIZE; | 165 | hash = tdb_hash(name) % SYMBOL_HASH_SIZE; |
| 162 | new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); | 166 | new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); |
| 163 | new->module = module; | 167 | new->module = module; |
| 168 | new->export = export; | ||
| 164 | return new; | 169 | return new; |
| 165 | } | 170 | } |
| 166 | 171 | ||
| @@ -179,16 +184,55 @@ static struct symbol *find_symbol(const char *name) | |||
| 179 | return NULL; | 184 | return NULL; |
| 180 | } | 185 | } |
| 181 | 186 | ||
| 187 | static struct { | ||
| 188 | const char *str; | ||
| 189 | enum export export; | ||
| 190 | } export_list[] = { | ||
| 191 | { .str = "EXPORT_SYMBOL", .export = export_plain }, | ||
| 192 | { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, | ||
| 193 | { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, | ||
| 194 | { .str = "(unknown)", .export = export_unknown }, | ||
| 195 | }; | ||
| 196 | |||
| 197 | |||
| 198 | static const char *export_str(enum export ex) | ||
| 199 | { | ||
| 200 | return export_list[ex].str; | ||
| 201 | } | ||
| 202 | |||
| 203 | static enum export export_no(const char * s) | ||
| 204 | { | ||
| 205 | int i; | ||
| 206 | for (i = 0; export_list[i].export != export_unknown; i++) { | ||
| 207 | if (strcmp(export_list[i].str, s) == 0) | ||
| 208 | return export_list[i].export; | ||
| 209 | } | ||
| 210 | return export_unknown; | ||
| 211 | } | ||
| 212 | |||
| 213 | static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) | ||
| 214 | { | ||
| 215 | if (sec == elf->export_sec) | ||
| 216 | return export_plain; | ||
| 217 | else if (sec == elf->export_gpl_sec) | ||
| 218 | return export_gpl; | ||
| 219 | else if (sec == elf->export_gpl_future_sec) | ||
| 220 | return export_gpl_future; | ||
| 221 | else | ||
| 222 | return export_unknown; | ||
| 223 | } | ||
| 224 | |||
| 182 | /** | 225 | /** |
| 183 | * Add an exported symbol - it may have already been added without a | 226 | * Add an exported symbol - it may have already been added without a |
| 184 | * CRC, in this case just update the CRC | 227 | * CRC, in this case just update the CRC |
| 185 | **/ | 228 | **/ |
| 186 | static struct symbol *sym_add_exported(const char *name, struct module *mod) | 229 | static struct symbol *sym_add_exported(const char *name, struct module *mod, |
| 230 | enum export export) | ||
| 187 | { | 231 | { |
| 188 | struct symbol *s = find_symbol(name); | 232 | struct symbol *s = find_symbol(name); |
| 189 | 233 | ||
| 190 | if (!s) { | 234 | if (!s) { |
| 191 | s = new_symbol(name, mod); | 235 | s = new_symbol(name, mod, export); |
| 192 | } else { | 236 | } else { |
| 193 | if (!s->preloaded) { | 237 | if (!s->preloaded) { |
| 194 | warn("%s: '%s' exported twice. Previous export " | 238 | warn("%s: '%s' exported twice. Previous export " |
| @@ -200,16 +244,17 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod) | |||
| 200 | s->preloaded = 0; | 244 | s->preloaded = 0; |
| 201 | s->vmlinux = is_vmlinux(mod->name); | 245 | s->vmlinux = is_vmlinux(mod->name); |
| 202 | s->kernel = 0; | 246 | s->kernel = 0; |
| 247 | s->export = export; | ||
| 203 | return s; | 248 | return s; |
| 204 | } | 249 | } |
| 205 | 250 | ||
| 206 | static void sym_update_crc(const char *name, struct module *mod, | 251 | static void sym_update_crc(const char *name, struct module *mod, |
| 207 | unsigned int crc) | 252 | unsigned int crc, enum export export) |
| 208 | { | 253 | { |
| 209 | struct symbol *s = find_symbol(name); | 254 | struct symbol *s = find_symbol(name); |
| 210 | 255 | ||
| 211 | if (!s) | 256 | if (!s) |
| 212 | s = new_symbol(name, mod); | 257 | s = new_symbol(name, mod, export); |
| 213 | s->crc = crc; | 258 | s->crc = crc; |
| 214 | s->crc_valid = 1; | 259 | s->crc_valid = 1; |
| 215 | } | 260 | } |
| @@ -309,13 +354,21 @@ static void parse_elf(struct elf_info *info, const char *filename) | |||
| 309 | for (i = 1; i < hdr->e_shnum; i++) { | 354 | for (i = 1; i < hdr->e_shnum; i++) { |
| 310 | const char *secstrings | 355 | const char *secstrings |
| 311 | = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 356 | = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
| 357 | const char *secname; | ||
| 312 | 358 | ||
| 313 | if (sechdrs[i].sh_offset > info->size) | 359 | if (sechdrs[i].sh_offset > info->size) |
| 314 | goto truncated; | 360 | goto truncated; |
| 315 | if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) { | 361 | secname = secstrings + sechdrs[i].sh_name; |
| 362 | if (strcmp(secname, ".modinfo") == 0) { | ||
| 316 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; | 363 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; |
| 317 | info->modinfo_len = sechdrs[i].sh_size; | 364 | info->modinfo_len = sechdrs[i].sh_size; |
| 318 | } | 365 | } else if (strcmp(secname, "__ksymtab") == 0) |
| 366 | info->export_sec = i; | ||
| 367 | else if (strcmp(secname, "__ksymtab_gpl") == 0) | ||
| 368 | info->export_gpl_sec = i; | ||
| 369 | else if (strcmp(secname, "__ksymtab_gpl_future") == 0) | ||
| 370 | info->export_gpl_future_sec = i; | ||
| 371 | |||
| 319 | if (sechdrs[i].sh_type != SHT_SYMTAB) | 372 | if (sechdrs[i].sh_type != SHT_SYMTAB) |
| 320 | continue; | 373 | continue; |
| 321 | 374 | ||
| @@ -353,6 +406,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
| 353 | Elf_Sym *sym, const char *symname) | 406 | Elf_Sym *sym, const char *symname) |
| 354 | { | 407 | { |
| 355 | unsigned int crc; | 408 | unsigned int crc; |
| 409 | enum export export = export_from_sec(info, sym->st_shndx); | ||
| 356 | 410 | ||
| 357 | switch (sym->st_shndx) { | 411 | switch (sym->st_shndx) { |
| 358 | case SHN_COMMON: | 412 | case SHN_COMMON: |
| @@ -362,7 +416,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
| 362 | /* CRC'd symbol */ | 416 | /* CRC'd symbol */ |
| 363 | if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { | 417 | if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { |
| 364 | crc = (unsigned int) sym->st_value; | 418 | crc = (unsigned int) sym->st_value; |
| 365 | sym_update_crc(symname + strlen(CRC_PFX), mod, crc); | 419 | sym_update_crc(symname + strlen(CRC_PFX), mod, crc, |
| 420 | export); | ||
| 366 | } | 421 | } |
| 367 | break; | 422 | break; |
| 368 | case SHN_UNDEF: | 423 | case SHN_UNDEF: |
| @@ -406,7 +461,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
| 406 | default: | 461 | default: |
| 407 | /* All exported symbols */ | 462 | /* All exported symbols */ |
| 408 | if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { | 463 | if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { |
| 409 | sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); | 464 | sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, |
| 465 | export); | ||
| 410 | } | 466 | } |
| 411 | if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) | 467 | if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) |
| 412 | mod->has_init = 1; | 468 | mod->has_init = 1; |
| @@ -1146,6 +1202,9 @@ static void write_if_changed(struct buffer *b, const char *fname) | |||
| 1146 | fclose(file); | 1202 | fclose(file); |
| 1147 | } | 1203 | } |
| 1148 | 1204 | ||
| 1205 | /* parse Module.symvers file. line format: | ||
| 1206 | * 0x12345678<tab>symbol<tab>module[<tab>export] | ||
| 1207 | **/ | ||
| 1149 | static void read_dump(const char *fname, unsigned int kernel) | 1208 | static void read_dump(const char *fname, unsigned int kernel) |
| 1150 | { | 1209 | { |
| 1151 | unsigned long size, pos = 0; | 1210 | unsigned long size, pos = 0; |
| @@ -1157,7 +1216,7 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
| 1157 | return; | 1216 | return; |
| 1158 | 1217 | ||
| 1159 | while ((line = get_next_line(&pos, file, size))) { | 1218 | while ((line = get_next_line(&pos, file, size))) { |
| 1160 | char *symname, *modname, *d; | 1219 | char *symname, *modname, *d, *export; |
| 1161 | unsigned int crc; | 1220 | unsigned int crc; |
| 1162 | struct module *mod; | 1221 | struct module *mod; |
| 1163 | struct symbol *s; | 1222 | struct symbol *s; |
| @@ -1168,8 +1227,9 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
| 1168 | if (!(modname = strchr(symname, '\t'))) | 1227 | if (!(modname = strchr(symname, '\t'))) |
| 1169 | goto fail; | 1228 | goto fail; |
| 1170 | *modname++ = '\0'; | 1229 | *modname++ = '\0'; |
| 1171 | if (strchr(modname, '\t')) | 1230 | if (!(export = strchr(modname, '\t'))) |
| 1172 | goto fail; | 1231 | *export++ = '\0'; |
| 1232 | |||
| 1173 | crc = strtoul(line, &d, 16); | 1233 | crc = strtoul(line, &d, 16); |
| 1174 | if (*symname == '\0' || *modname == '\0' || *d != '\0') | 1234 | if (*symname == '\0' || *modname == '\0' || *d != '\0') |
| 1175 | goto fail; | 1235 | goto fail; |
| @@ -1181,10 +1241,10 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
| 1181 | mod = new_module(NOFAIL(strdup(modname))); | 1241 | mod = new_module(NOFAIL(strdup(modname))); |
| 1182 | mod->skip = 1; | 1242 | mod->skip = 1; |
| 1183 | } | 1243 | } |
| 1184 | s = sym_add_exported(symname, mod); | 1244 | s = sym_add_exported(symname, mod, export_no(export)); |
| 1185 | s->kernel = kernel; | 1245 | s->kernel = kernel; |
| 1186 | s->preloaded = 1; | 1246 | s->preloaded = 1; |
| 1187 | sym_update_crc(symname, mod, crc); | 1247 | sym_update_crc(symname, mod, crc, export_no(export)); |
| 1188 | } | 1248 | } |
| 1189 | return; | 1249 | return; |
| 1190 | fail: | 1250 | fail: |
| @@ -1214,9 +1274,10 @@ static void write_dump(const char *fname) | |||
| 1214 | symbol = symbolhash[n]; | 1274 | symbol = symbolhash[n]; |
| 1215 | while (symbol) { | 1275 | while (symbol) { |
| 1216 | if (dump_sym(symbol)) | 1276 | if (dump_sym(symbol)) |
| 1217 | buf_printf(&buf, "0x%08x\t%s\t%s\n", | 1277 | buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n", |
| 1218 | symbol->crc, symbol->name, | 1278 | symbol->crc, symbol->name, |
| 1219 | symbol->module->name); | 1279 | symbol->module->name, |
| 1280 | export_str(symbol->export)); | ||
| 1220 | symbol = symbol->next; | 1281 | symbol = symbol->next; |
| 1221 | } | 1282 | } |
| 1222 | } | 1283 | } |
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 861d866fcd83..f7ee3a3fde14 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
| @@ -115,6 +115,9 @@ struct elf_info { | |||
| 115 | Elf_Shdr *sechdrs; | 115 | Elf_Shdr *sechdrs; |
| 116 | Elf_Sym *symtab_start; | 116 | Elf_Sym *symtab_start; |
| 117 | Elf_Sym *symtab_stop; | 117 | Elf_Sym *symtab_stop; |
| 118 | Elf_Section export_sec; | ||
| 119 | Elf_Section export_gpl_sec; | ||
| 120 | Elf_Section export_gpl_future_sec; | ||
| 118 | const char *strtab; | 121 | const char *strtab; |
| 119 | char *modinfo; | 122 | char *modinfo; |
| 120 | unsigned int modinfo_len; | 123 | unsigned int modinfo_len; |
