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 ...
16 /* Are we using CONFIG_MODVERSIONS? */
18 /* Do we have vmlinux? */
22 fatal(const char *fmt
, ...)
26 fprintf(stderr
, "FATAL: ");
28 va_start(arglist
, fmt
);
29 vfprintf(stderr
, fmt
, arglist
);
36 warn(const char *fmt
, ...)
40 fprintf(stderr
, "WARNING: ");
42 va_start(arglist
, fmt
);
43 vfprintf(stderr
, fmt
, arglist
);
47 #define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
49 void *do_nofail(void *ptr
, const char *file
, int line
, const char *expr
)
52 fatal("Memory allocation failure %s line %d: %s.\n",
58 /* A list of all modules we processed */
60 static struct module
*modules
;
63 new_module(char *modname
)
68 /* strip trailing .o */
69 p
= strstr(modname
, ".o");
73 mod
= NOFAIL(malloc(sizeof(*mod
)));
74 memset(mod
, 0, sizeof(*mod
));
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
);
189 if (fstat(fd
, &st
) != 0) {
195 map
= mmap(NULL
, *size
, PROT_READ
|PROT_WRITE
, MAP_PRIVATE
, fd
, 0);
196 if (mmap
== MAP_FAILED
) {
205 parse_elf(struct elf_info
*info
, const char *filename
)
208 Elf_Ehdr
*hdr
= info
->hdr
;
212 hdr
= grab_file(filename
, &info
->size
);
214 if (info
->size
< sizeof(*hdr
))
217 /* Fix endianness in ELF header */
218 hdr
->e_shoff
= TO_NATIVE(hdr
->e_shoff
);
219 hdr
->e_shstrndx
= TO_NATIVE(hdr
->e_shstrndx
);
220 hdr
->e_shnum
= TO_NATIVE(hdr
->e_shnum
);
221 sechdrs
= (void *)hdr
+ hdr
->e_shoff
;
222 info
->sechdrs
= sechdrs
;
224 /* Fix endianness in section headers */
225 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
226 sechdrs
[i
].sh_type
= TO_NATIVE(sechdrs
[i
].sh_type
);
227 sechdrs
[i
].sh_offset
= TO_NATIVE(sechdrs
[i
].sh_offset
);
228 sechdrs
[i
].sh_size
= TO_NATIVE(sechdrs
[i
].sh_size
);
229 sechdrs
[i
].sh_link
= TO_NATIVE(sechdrs
[i
].sh_link
);
231 /* Find symbol table. */
232 for (i
= 1; i
< hdr
->e_shnum
; i
++) {
233 if (sechdrs
[i
].sh_offset
> info
->size
)
235 if (sechdrs
[i
].sh_type
!= SHT_SYMTAB
)
238 info
->symtab_start
= (void *)hdr
+ sechdrs
[i
].sh_offset
;
239 info
->symtab_stop
= (void *)hdr
+ sechdrs
[i
].sh_offset
240 + sechdrs
[i
].sh_size
;
241 info
->strtab
= (void *)hdr
+
242 sechdrs
[sechdrs
[i
].sh_link
].sh_offset
;
244 if (!info
->symtab_start
) {
245 fprintf(stderr
, "modpost: %s no symtab?\n", filename
);
248 /* Fix endianness in symbols */
249 for (sym
= info
->symtab_start
; sym
< info
->symtab_stop
; sym
++) {
250 sym
->st_shndx
= TO_NATIVE(sym
->st_shndx
);
251 sym
->st_name
= TO_NATIVE(sym
->st_name
);
252 sym
->st_value
= TO_NATIVE(sym
->st_value
);
253 sym
->st_size
= TO_NATIVE(sym
->st_size
);
258 fprintf(stderr
, "modpost: %s is truncated.\n", filename
);
263 parse_elf_finish(struct elf_info
*info
)
265 munmap(info
->hdr
, info
->size
);
268 #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
269 #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
272 handle_modversions(struct module
*mod
, struct elf_info
*info
,
273 Elf_Sym
*sym
, const char *symname
)
278 switch (sym
->st_shndx
) {
280 fprintf(stderr
, "*** Warning: \"%s\" [%s] is COMMON symbol\n",
285 if (memcmp(symname
, CRC_PFX
, strlen(CRC_PFX
)) == 0) {
286 crc
= (unsigned int) sym
->st_value
;
287 add_exported_symbol(symname
+ strlen(CRC_PFX
),
293 /* undefined symbol */
294 if (ELF_ST_BIND(sym
->st_info
) != STB_GLOBAL
)
296 /* ignore global offset table */
297 if (strcmp(symname
, "_GLOBAL_OFFSET_TABLE_") == 0)
299 if (info
->hdr
->e_machine
== EM_SPARC
||
300 info
->hdr
->e_machine
== EM_SPARCV9
) {
301 /* Ignore register directives. */
302 if (ELF_ST_TYPE(sym
->st_info
) == STT_REGISTER
)
306 if (memcmp(symname
, MODULE_SYMBOL_PREFIX
,
307 strlen(MODULE_SYMBOL_PREFIX
)) == 0) {
308 s
= alloc_symbol(symname
+
309 strlen(MODULE_SYMBOL_PREFIX
));
311 s
->next
= mod
->unres
;
316 /* All exported symbols */
317 if (memcmp(symname
, KSYMTAB_PFX
, strlen(KSYMTAB_PFX
)) == 0) {
318 add_exported_symbol(symname
+ strlen(KSYMTAB_PFX
),
326 read_symbols(char *modname
)
330 struct elf_info info
= { };
334 /* When there's no vmlinux, don't print warnings about
335 * unresolved symbols (since there'll be too many ;) */
336 if (strcmp(modname
, "vmlinux") == 0)
339 parse_elf(&info
, modname
);
341 mod
= new_module(modname
);
343 for (sym
= info
.symtab_start
; sym
< info
.symtab_stop
; sym
++) {
344 symname
= info
.strtab
+ sym
->st_name
;
346 handle_modversions(mod
, &info
, sym
, symname
);
347 handle_moddevtable(mod
, &info
, sym
, symname
);
349 parse_elf_finish(&info
);
351 /* Our trick to get versioning for struct_module - it's
352 * never passed as an argument to an exported function, so
353 * the automatic versioning doesn't pick it up, but it's really
354 * important anyhow */
356 s
= alloc_symbol("struct_module");
358 s
->next
= mod
->unres
;
365 /* We first write the generated file into memory using the
366 * following helper, then compare to the file on disk and
367 * only update the later if anything changed */
369 void __attribute__((format(printf
, 2, 3)))
370 buf_printf(struct buffer
*buf
, const char *fmt
, ...)
377 len
= vsnprintf(tmp
, SZ
, fmt
, ap
);
378 if (buf
->size
- buf
->pos
< len
+ 1) {
380 buf
->p
= realloc(buf
->p
, buf
->size
);
382 strncpy(buf
->p
+ buf
->pos
, tmp
, len
+ 1);
388 buf_write(struct buffer
*buf
, const char *s
, int len
)
390 if (buf
->size
- buf
->pos
< len
) {
392 buf
->p
= realloc(buf
->p
, buf
->size
);
394 strncpy(buf
->p
+ buf
->pos
, s
, len
);
398 /* Header for the generated file */
401 add_header(struct buffer
*b
)
403 buf_printf(b
, "#include <linux/module.h>\n");
404 buf_printf(b
, "#include <linux/vermagic.h>\n");
405 buf_printf(b
, "#include <linux/compiler.h>\n");
407 buf_printf(b
, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
410 /* Record CRCs for unresolved symbols */
413 add_versions(struct buffer
*b
, struct module
*mod
)
415 struct symbol
*s
, *exp
;
417 for (s
= mod
->unres
; s
; s
= s
->next
) {
418 exp
= find_symbol(s
->name
);
419 if (!exp
|| exp
->module
== mod
) {
421 fprintf(stderr
, "*** Warning: \"%s\" [%s.ko] "
422 "undefined!\n", s
->name
, mod
->name
);
425 s
->module
= exp
->module
;
426 s
->crc_valid
= exp
->crc_valid
;
434 buf_printf(b
, "static const struct modversion_info ____versions[]\n");
435 buf_printf(b
, "__attribute__((section(\"__versions\"))) = {\n");
437 for (s
= mod
->unres
; s
; s
= s
->next
) {
442 fprintf(stderr
, "*** Warning: \"%s\" [%s.ko] "
447 buf_printf(b
, "\t{ %#8x, \"%s\" },\n", s
->crc
, s
->name
);
450 buf_printf(b
, "};\n");
454 add_depends(struct buffer
*b
, struct module
*mod
, struct module
*modules
)
460 for (m
= modules
; m
; m
= m
->next
) {
461 if (strcmp(m
->name
, "vmlinux") == 0)
468 buf_printf(b
, "static const char __module_depends[]\n");
469 buf_printf(b
, "__attribute_used__\n");
470 buf_printf(b
, "__attribute__((section(\".modinfo\"))) =\n");
471 buf_printf(b
, "\"depends=");
472 for (s
= mod
->unres
; s
; s
= s
->next
) {
480 buf_printf(b
, "%s%s", first
? "" : ",",
481 strrchr(s
->module
->name
, '/') + 1);
484 buf_printf(b
, "\";\n");
488 write_if_changed(struct buffer
*b
, const char *fname
)
494 file
= fopen(fname
, "r");
498 if (fstat(fileno(file
), &st
) < 0)
501 if (st
.st_size
!= b
->pos
)
504 tmp
= NOFAIL(malloc(b
->pos
));
505 if (fread(tmp
, 1, b
->pos
, file
) != b
->pos
)
508 if (memcmp(tmp
, b
->p
, b
->pos
) != 0)
520 file
= fopen(fname
, "w");
525 if (fwrite(b
->p
, 1, b
->pos
, file
) != b
->pos
) {
533 main(int argc
, char **argv
)
536 struct buffer buf
= { };
539 for (; argv
[1]; argv
++) {
540 read_symbols(argv
[1]);
543 for (mod
= modules
; mod
; mod
= mod
->next
) {
544 if (strcmp(mod
->name
, "vmlinux") == 0)
550 add_versions(&buf
, mod
);
551 add_depends(&buf
, mod
, modules
);
552 add_moddevtable(&buf
, mod
);
554 sprintf(fname
, "%s.mod.c", mod
->name
);
555 write_if_changed(&buf
, fname
);