Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ram Pai and committed by
Sam Ravnborg
bd5cbced 031ecc6d

+80 -16
+77 -16
scripts/mod/modpost.c
··· 22 22 static int all_versions = 0; 23 23 /* If we are modposting external module set to 1 */ 24 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 28 void fatal(const char *fmt, ...) 27 29 { ··· 120 118 unsigned int kernel:1; /* 1 if symbol is from kernel 121 119 * (only for external modules) **/ 122 120 unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ 121 + enum export export; /* Type of export */ 123 122 char name[0]; 124 123 }; 125 124 ··· 156 153 } 157 154 158 155 /* For the hash of exported symbols */ 159 - static struct symbol *new_symbol(const char *name, struct module *module) 156 + static struct symbol *new_symbol(const char *name, struct module *module, 157 + enum export export) 160 158 { 161 159 unsigned int hash; 162 160 struct symbol *new; ··· 165 161 hash = tdb_hash(name) % SYMBOL_HASH_SIZE; 166 162 new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); 167 163 new->module = module; 164 + new->export = export; 168 165 return new; 169 166 } 170 167 ··· 184 179 return NULL; 185 180 } 186 181 182 + static struct { 183 + const char *str; 184 + enum export export; 185 + } export_list[] = { 186 + { .str = "EXPORT_SYMBOL", .export = export_plain }, 187 + { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, 188 + { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, 189 + { .str = "(unknown)", .export = export_unknown }, 190 + }; 191 + 192 + 193 + static const char *export_str(enum export ex) 194 + { 195 + return export_list[ex].str; 196 + } 197 + 198 + static enum export export_no(const char * s) 199 + { 200 + int i; 201 + for (i = 0; export_list[i].export != export_unknown; i++) { 202 + if (strcmp(export_list[i].str, s) == 0) 203 + return export_list[i].export; 204 + } 205 + return export_unknown; 206 + } 207 + 208 + static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) 209 + { 210 + if (sec == elf->export_sec) 211 + return export_plain; 212 + else if (sec == elf->export_gpl_sec) 213 + return export_gpl; 214 + else if (sec == elf->export_gpl_future_sec) 215 + return export_gpl_future; 216 + else 217 + return export_unknown; 218 + } 219 + 187 220 /** 188 221 * Add an exported symbol - it may have already been added without a 189 222 * CRC, in this case just update the CRC 190 223 **/ 191 - static struct symbol *sym_add_exported(const char *name, struct module *mod) 224 + static struct symbol *sym_add_exported(const char *name, struct module *mod, 225 + enum export export) 192 226 { 193 227 struct symbol *s = find_symbol(name); 194 228 195 229 if (!s) { 196 - s = new_symbol(name, mod); 230 + s = new_symbol(name, mod, export); 197 231 } else { 198 232 if (!s->preloaded) { 199 233 warn("%s: '%s' exported twice. Previous export " ··· 244 200 s->preloaded = 0; 245 201 s->vmlinux = is_vmlinux(mod->name); 246 202 s->kernel = 0; 203 + s->export = export; 247 204 return s; 248 205 } 249 206 250 207 static void sym_update_crc(const char *name, struct module *mod, 251 - unsigned int crc) 208 + unsigned int crc, enum export export) 252 209 { 253 210 struct symbol *s = find_symbol(name); 254 211 255 212 if (!s) 256 - s = new_symbol(name, mod); 213 + s = new_symbol(name, mod, export); 257 214 s->crc = crc; 258 215 s->crc_valid = 1; 259 216 } ··· 354 309 for (i = 1; i < hdr->e_shnum; i++) { 355 310 const char *secstrings 356 311 = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 312 + const char *secname; 357 313 358 314 if (sechdrs[i].sh_offset > info->size) 359 315 goto truncated; 360 - if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) { 316 + secname = secstrings + sechdrs[i].sh_name; 317 + if (strcmp(secname, ".modinfo") == 0) { 361 318 info->modinfo = (void *)hdr + sechdrs[i].sh_offset; 362 319 info->modinfo_len = sechdrs[i].sh_size; 363 - } 320 + } else if (strcmp(secname, "__ksymtab") == 0) 321 + info->export_sec = i; 322 + else if (strcmp(secname, "__ksymtab_gpl") == 0) 323 + info->export_gpl_sec = i; 324 + else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 325 + info->export_gpl_future_sec = i; 326 + 364 327 if (sechdrs[i].sh_type != SHT_SYMTAB) 365 328 continue; 366 329 ··· 406 353 Elf_Sym *sym, const char *symname) 407 354 { 408 355 unsigned int crc; 356 + enum export export = export_from_sec(info, sym->st_shndx); 409 357 410 358 switch (sym->st_shndx) { 411 359 case SHN_COMMON: ··· 416 362 /* CRC'd symbol */ 417 363 if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { 418 364 crc = (unsigned int) sym->st_value; 419 - sym_update_crc(symname + strlen(CRC_PFX), mod, crc); 365 + sym_update_crc(symname + strlen(CRC_PFX), mod, crc, 366 + export); 420 367 } 421 368 break; 422 369 case SHN_UNDEF: ··· 461 406 default: 462 407 /* All exported symbols */ 463 408 if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { 464 - sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); 409 + sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, 410 + export); 465 411 } 466 412 if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) 467 413 mod->has_init = 1; ··· 1202 1146 fclose(file); 1203 1147 } 1204 1148 1149 + /* parse Module.symvers file. line format: 1150 + * 0x12345678<tab>symbol<tab>module[<tab>export] 1151 + **/ 1205 1152 static void read_dump(const char *fname, unsigned int kernel) 1206 1153 { 1207 1154 unsigned long size, pos = 0; ··· 1216 1157 return; 1217 1158 1218 1159 while ((line = get_next_line(&pos, file, size))) { 1219 - char *symname, *modname, *d; 1160 + char *symname, *modname, *d, *export; 1220 1161 unsigned int crc; 1221 1162 struct module *mod; 1222 1163 struct symbol *s; ··· 1227 1168 if (!(modname = strchr(symname, '\t'))) 1228 1169 goto fail; 1229 1170 *modname++ = '\0'; 1230 - if (strchr(modname, '\t')) 1231 - goto fail; 1171 + if (!(export = strchr(modname, '\t'))) 1172 + *export++ = '\0'; 1173 + 1232 1174 crc = strtoul(line, &d, 16); 1233 1175 if (*symname == '\0' || *modname == '\0' || *d != '\0') 1234 1176 goto fail; ··· 1241 1181 mod = new_module(NOFAIL(strdup(modname))); 1242 1182 mod->skip = 1; 1243 1183 } 1244 - s = sym_add_exported(symname, mod); 1184 + s = sym_add_exported(symname, mod, export_no(export)); 1245 1185 s->kernel = kernel; 1246 1186 s->preloaded = 1; 1247 - sym_update_crc(symname, mod, crc); 1187 + sym_update_crc(symname, mod, crc, export_no(export)); 1248 1188 } 1249 1189 return; 1250 1190 fail: ··· 1274 1214 symbol = symbolhash[n]; 1275 1215 while (symbol) { 1276 1216 if (dump_sym(symbol)) 1277 - buf_printf(&buf, "0x%08x\t%s\t%s\n", 1217 + buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n", 1278 1218 symbol->crc, symbol->name, 1279 - symbol->module->name); 1219 + symbol->module->name, 1220 + export_str(symbol->export)); 1280 1221 symbol = symbol->next; 1281 1222 } 1282 1223 }
+3
scripts/mod/modpost.h
··· 115 115 Elf_Shdr *sechdrs; 116 116 Elf_Sym *symtab_start; 117 117 Elf_Sym *symtab_stop; 118 + Elf_Section export_sec; 119 + Elf_Section export_gpl_sec; 120 + Elf_Section export_gpl_future_sec; 118 121 const char *strtab; 119 122 char *modinfo; 120 123 unsigned int modinfo_len;