1 /* Postprocess module symbol versions
3 * Copyright 2003 Kai Germaschewski
4 * 2002-2003 Rusty Russell, IBM Corporation
6 * Based in part on module-init-tools/depmod.c,file2alias
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
11 * Usage: modpost vmlinux module1.o module2.o ...
17 /* Are we using CONFIG_MODVERSIONS? */
19 /* Do we have vmlinux? */
23 fatal(const char *fmt
, ...)
27 fprintf(stderr
, "FATAL: ");
29 va_start(arglist
, fmt
);
30 vfprintf(stderr
, fmt
, arglist
);
37 warn(const char *fmt
, ...)
41 fprintf(stderr
, "WARNING: ");
43 va_start(arglist
, fmt
);
44 vfprintf(stderr
, fmt
, arglist
);
48 void *do_nofail(void *ptr
, const char *file
, int line
, const char *expr
)
51 fatal("Memory allocation failure %s line %d: %s.\n",
57 /* A list of all modules we processed */
59 static struct module
*modules
;
62 new_module(char *modname
)
67 mod
= NOFAIL(malloc(sizeof(*mod
)));
68 memset(mod
, 0, sizeof(*mod
));
69 p
= NOFAIL(strdup(modname
));
71 /* strip trailing .o */
72 if ((s
= strrchr(p
, '.')) != NULL
)
73 if (strcmp(s
, ".o") == 0)
84 /* A hash of all exported symbols,
85 * struct symbol is also used for lists of unresolved symbols */
87 #define SYMBOL_HASH_SIZE 1024
91 struct module
*module
;
97 static struct symbol
*symbolhash
[SYMBOL_HASH_SIZE
];
99 /* This is based on the hash agorithm from gdbm, via tdb */
100 static inline unsigned int tdb_hash(const char *name
)
102 unsigned value
; /* Used to compute the hash value. */
103 unsigned i
; /* Used to cycle through random values. */
105 /* Set the initial value from the key size. */
106 for (value
= 0x238F13AF * strlen(name
), i
=0; name
[i
]; i
++)
107 value
= (value
+ (((unsigned char *)name
)[i
] << (i
*5 % 24)));
109 return (1103515243 * value
+ 12345);
112 /* Allocate a new symbols for use in the hash of exported symbols or
113 * the list of unresolved symbols per module */
116 alloc_symbol(const char *name
)
118 struct symbol
*s
= NOFAIL(malloc(sizeof(*s
) + strlen(name
) + 1));
120 memset(s
, 0, sizeof(*s
));
121 strcpy(s
->name
, name
);
125 /* For the hash of exported symbols */
128 new_symbol(const char *name
, struct module
*module
, unsigned int *crc
)
131 struct symbol
*new = alloc_symbol(name
);
133 new->module
= module
;
139 hash
= tdb_hash(name
) % SYMBOL_HASH_SIZE
;
140 new->next
= symbolhash
[hash
];
141 symbolhash
[hash
] = new;
145 find_symbol(const char *name
)
149 /* For our purposes, .foo matches foo. PPC64 needs this. */
153 for (s
= symbolhash
[tdb_hash(name
) % SYMBOL_HASH_SIZE
]; s
; s
=s
->next
) {
154 if (strcmp(s
->name
, name
) == 0)
160 /* Add an exported symbol - it may have already been added without a
161 * CRC, in this case just update the CRC */
163 add_exported_symbol(const char *name
, struct module
*module
, unsigned int *crc
)
165 struct symbol
*s
= find_symbol(name
);
168 new_symbol(name
, modules
, crc
);
178 grab_file(const char *filename
, unsigned long *size
)
184 fd
= open(filename
, O_RDONLY
);
185 if (fstat(fd
, &st
) != 0)
189 map
= mmap(NULL
, *size
, PROT_READ
|PROT_WRITE
, MAP_PRIVATE
, fd
, 0);
192 if (map
== MAP_FAILED
)
198 Return a copy of the next line in a mmap'ed file.
199 spaces in the beginning of the line is trimmed away.
200 Return a pointer to a static buffer.
203 get_next_line(unsigned long *pos
, void *file
, unsigned long size
)
205 static char line
[4096];
208 char *p
= (char *)file
+ *pos
;
211 for (; *pos
< size
; (*pos
)++)
213 if (skip
&& isspace(*p
)) {
218 if (*p
!= '\n' && (*pos
< size
)) {
222 break; /* Too long, stop */
234 release_file(void *file
, unsigned long size
)
240 parse_elf(struct elf_info
*info
, const char *filename
)
243 Elf_Ehdr
*hdr
= info
->hdr
;
247 hdr
= grab_file(filename
, &info
->size
);
253 if (info
->size
< sizeof(*hdr
))
256 /* Fix endianness in ELF header */
257 hdr
->e_shoff
= TO_NATIVE(hdr
->e_shoff
);
258 hdr
->e_shstrndx
= TO_NATIVE(hdr
->e_shstrndx
);
259 hdr
->e_shnum
= TO_NATIVE(hdr
->e_shnum
);
260 sechdrs
= (void *)hdr
+ hdr
->e_shoff
;
261 info
->sechdrs
= sechdrs
;
263 /* Fix endianness in section headers */
264 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
265 sechdrs
[i
].sh_type
= TO_NATIVE(sechdrs
[i
].sh_type
);
266 sechdrs
[i
].sh_offset
= TO_NATIVE(sechdrs
[i
].sh_offset
);
267 sechdrs
[i
].sh_size
= TO_NATIVE(sechdrs
[i
].sh_size
);
268 sechdrs
[i
].sh_link
= TO_NATIVE(sechdrs
[i
].sh_link
);
269 sechdrs
[i
].sh_name
= TO_NATIVE(sechdrs
[i
].sh_name
);
271 /* Find symbol table. */
272 for (i
= 1; i
< hdr
->e_shnum
; i
++) {
273 const char *secstrings
274 = (void *)hdr
+ sechdrs
[hdr
->e_shstrndx
].sh_offset
;
276 if (sechdrs
[i
].sh_offset
> info
->size
)
278 if (strcmp(secstrings
+sechdrs
[i
].sh_name
, ".modinfo") == 0) {
279 info
->modinfo
= (void *)hdr
+ sechdrs
[i
].sh_offset
;
280 info
->modinfo_len
= sechdrs
[i
].sh_size
;
282 if (sechdrs
[i
].sh_type
!= SHT_SYMTAB
)
285 info
->symtab_start
= (void *)hdr
+ sechdrs
[i
].sh_offset
;
286 info
->symtab_stop
= (void *)hdr
+ sechdrs
[i
].sh_offset
287 + sechdrs
[i
].sh_size
;
288 info
->strtab
= (void *)hdr
+
289 sechdrs
[sechdrs
[i
].sh_link
].sh_offset
;
291 if (!info
->symtab_start
) {
292 fprintf(stderr
, "modpost: %s no symtab?\n", filename
);
295 /* Fix endianness in symbols */
296 for (sym
= info
->symtab_start
; sym
< info
->symtab_stop
; sym
++) {
297 sym
->st_shndx
= TO_NATIVE(sym
->st_shndx
);
298 sym
->st_name
= TO_NATIVE(sym
->st_name
);
299 sym
->st_value
= TO_NATIVE(sym
->st_value
);
300 sym
->st_size
= TO_NATIVE(sym
->st_size
);
305 fprintf(stderr
, "modpost: %s is truncated.\n", filename
);
310 parse_elf_finish(struct elf_info
*info
)
312 release_file(info
->hdr
, info
->size
);
315 #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
316 #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
319 handle_modversions(struct module
*mod
, struct elf_info
*info
,
320 Elf_Sym
*sym
, const char *symname
)
325 switch (sym
->st_shndx
) {
327 fprintf(stderr
, "*** Warning: \"%s\" [%s] is COMMON symbol\n",
332 if (memcmp(symname
, CRC_PFX
, strlen(CRC_PFX
)) == 0) {
333 crc
= (unsigned int) sym
->st_value
;
334 add_exported_symbol(symname
+ strlen(CRC_PFX
),
340 /* undefined symbol */
341 if (ELF_ST_BIND(sym
->st_info
) != STB_GLOBAL
)
343 /* ignore global offset table */
344 if (strcmp(symname
, "_GLOBAL_OFFSET_TABLE_") == 0)
347 if (info
->hdr
->e_machine
== EM_SPARC
||
348 info
->hdr
->e_machine
== EM_SPARCV9
) {
349 /* Ignore register directives. */
350 if (ELF_ST_TYPE(sym
->st_info
) == STT_REGISTER
)
355 if (memcmp(symname
, MODULE_SYMBOL_PREFIX
,
356 strlen(MODULE_SYMBOL_PREFIX
)) == 0) {
357 s
= alloc_symbol(symname
+
358 strlen(MODULE_SYMBOL_PREFIX
));
360 s
->next
= mod
->unres
;
365 /* All exported symbols */
366 if (memcmp(symname
, KSYMTAB_PFX
, strlen(KSYMTAB_PFX
)) == 0) {
367 add_exported_symbol(symname
+ strlen(KSYMTAB_PFX
),
375 is_vmlinux(const char *modname
)
379 if ((myname
= strrchr(modname
, '/')))
384 return strcmp(myname
, "vmlinux") == 0;
388 read_symbols(char *modname
)
392 struct elf_info info
= { };
396 /* When there's no vmlinux, don't print warnings about
397 * unresolved symbols (since there'll be too many ;) */
398 have_vmlinux
= is_vmlinux(modname
);
400 parse_elf(&info
, modname
);
402 mod
= new_module(modname
);
404 for (sym
= info
.symtab_start
; sym
< info
.symtab_stop
; sym
++) {
405 symname
= info
.strtab
+ sym
->st_name
;
407 handle_modversions(mod
, &info
, sym
, symname
);
408 handle_moddevtable(mod
, &info
, sym
, symname
);
410 maybe_frob_version(modname
, info
.modinfo
, info
.modinfo_len
,
411 (void *)info
.modinfo
- (void *)info
.hdr
);
412 parse_elf_finish(&info
);
414 /* Our trick to get versioning for struct_module - it's
415 * never passed as an argument to an exported function, so
416 * the automatic versioning doesn't pick it up, but it's really
417 * important anyhow */
419 s
= alloc_symbol("struct_module");
421 s
->next
= mod
->unres
;
428 /* We first write the generated file into memory using the
429 * following helper, then compare to the file on disk and
430 * only update the later if anything changed */
432 void __attribute__((format(printf
, 2, 3)))
433 buf_printf(struct buffer
*buf
, const char *fmt
, ...)
440 len
= vsnprintf(tmp
, SZ
, fmt
, ap
);
441 if (buf
->size
- buf
->pos
< len
+ 1) {
443 buf
->p
= realloc(buf
->p
, buf
->size
);
445 strncpy(buf
->p
+ buf
->pos
, tmp
, len
+ 1);
451 buf_write(struct buffer
*buf
, const char *s
, int len
)
453 if (buf
->size
- buf
->pos
< len
) {
455 buf
->p
= realloc(buf
->p
, buf
->size
);
457 strncpy(buf
->p
+ buf
->pos
, s
, len
);
461 /* Header for the generated file */
464 add_header(struct buffer
*b
)
466 buf_printf(b
, "#include <linux/module.h>\n");
467 buf_printf(b
, "#include <linux/vermagic.h>\n");
468 buf_printf(b
, "#include <linux/compiler.h>\n");
470 buf_printf(b
, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
473 /* Record CRCs for unresolved symbols */
476 add_versions(struct buffer
*b
, struct module
*mod
)
478 struct symbol
*s
, *exp
;
480 for (s
= mod
->unres
; s
; s
= s
->next
) {
481 exp
= find_symbol(s
->name
);
482 if (!exp
|| exp
->module
== mod
) {
484 fprintf(stderr
, "*** Warning: \"%s\" [%s.ko] "
485 "undefined!\n", s
->name
, mod
->name
);
488 s
->module
= exp
->module
;
489 s
->crc_valid
= exp
->crc_valid
;
497 buf_printf(b
, "static const struct modversion_info ____versions[]\n");
498 buf_printf(b
, "__attribute_used__\n");
499 buf_printf(b
, "__attribute__((section(\"__versions\"))) = {\n");
501 for (s
= mod
->unres
; s
; s
= s
->next
) {
506 fprintf(stderr
, "*** Warning: \"%s\" [%s.ko] "
511 buf_printf(b
, "\t{ %#8x, \"%s\" },\n", s
->crc
, s
->name
);
514 buf_printf(b
, "};\n");
518 add_depends(struct buffer
*b
, struct module
*mod
, struct module
*modules
)
524 for (m
= modules
; m
; m
= m
->next
) {
525 m
->seen
= is_vmlinux(m
->name
);
529 buf_printf(b
, "static const char __module_depends[]\n");
530 buf_printf(b
, "__attribute_used__\n");
531 buf_printf(b
, "__attribute__((section(\".modinfo\"))) =\n");
532 buf_printf(b
, "\"depends=");
533 for (s
= mod
->unres
; s
; s
= s
->next
) {
541 buf_printf(b
, "%s%s", first
? "" : ",",
542 strrchr(s
->module
->name
, '/') + 1);
545 buf_printf(b
, "\";\n");
549 write_if_changed(struct buffer
*b
, const char *fname
)
555 file
= fopen(fname
, "r");
559 if (fstat(fileno(file
), &st
) < 0)
562 if (st
.st_size
!= b
->pos
)
565 tmp
= NOFAIL(malloc(b
->pos
));
566 if (fread(tmp
, 1, b
->pos
, file
) != b
->pos
)
569 if (memcmp(tmp
, b
->p
, b
->pos
) != 0)
581 file
= fopen(fname
, "w");
586 if (fwrite(b
->p
, 1, b
->pos
, file
) != b
->pos
) {
594 main(int argc
, char **argv
)
597 struct buffer buf
= { };
600 for (; argv
[1]; argv
++) {
601 read_symbols(argv
[1]);
604 for (mod
= modules
; mod
; mod
= mod
->next
) {
605 if (is_vmlinux(mod
->name
))
611 add_versions(&buf
, mod
);
612 add_depends(&buf
, mod
, modules
);
613 add_moddevtable(&buf
, mod
);
615 sprintf(fname
, "%s.mod.c", mod
->name
);
616 write_if_changed(&buf
, fname
);