aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod/modpost.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r--scripts/mod/modpost.c93
1 files changed, 77 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;
22static int all_versions = 0; 22static int all_versions = 0;
23/* If we are modposting external module set to 1 */ 23/* If we are modposting external module set to 1 */
24static int external_module = 0; 24static int external_module = 0;
25/* How a symbol is exported */
26enum export {export_plain, export_gpl, export_gpl_future, export_unknown};
25 27
26void fatal(const char *fmt, ...) 28void 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 */
156static struct symbol *new_symbol(const char *name, struct module *module) 159static 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
187static 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
198static const char *export_str(enum export ex)
199{
200 return export_list[ex].str;
201}
202
203static 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
213static 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 **/
186static struct symbol *sym_add_exported(const char *name, struct module *mod) 229static 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
206static void sym_update_crc(const char *name, struct module *mod, 251static 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 **/
1149static void read_dump(const char *fname, unsigned int kernel) 1208static 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;
1190fail: 1250fail:
@@ -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 }