1 | /* Postprocess module symbol versions |
2 | * |
3 | * Copyright 2003 Kai Germaschewski |
4 | * Copyright 2002-2004 Rusty Russell, IBM Corporation |
5 | * Copyright 2006-2008 Sam Ravnborg |
6 | * Based in part on module-init-tools/depmod.c,file2alias |
7 | * |
8 | * This software may be used and distributed according to the terms |
9 | * of the GNU General Public License, incorporated herein by reference. |
10 | * |
11 | * Usage: modpost vmlinux module1.o module2.o ... |
12 | */ |
13 | |
14 | #define _GNU_SOURCE |
15 | #include <elf.h> |
16 | #include <fnmatch.h> |
17 | #include <stdio.h> |
18 | #include <ctype.h> |
19 | #include <string.h> |
20 | #include <limits.h> |
21 | #include <stdbool.h> |
22 | #include <errno.h> |
23 | #include "modpost.h" |
24 | #include "../../include/linux/license.h" |
25 | |
26 | static bool module_enabled; |
27 | /* Are we using CONFIG_MODVERSIONS? */ |
28 | static bool modversions; |
29 | /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ |
30 | static bool all_versions; |
31 | /* If we are modposting external module set to 1 */ |
32 | static bool external_module; |
33 | /* Only warn about unresolved symbols */ |
34 | static bool warn_unresolved; |
35 | |
36 | static int sec_mismatch_count; |
37 | static bool sec_mismatch_warn_only = true; |
38 | /* Trim EXPORT_SYMBOLs that are unused by in-tree modules */ |
39 | static bool trim_unused_exports; |
40 | |
41 | /* ignore missing files */ |
42 | static bool ignore_missing_files; |
43 | /* If set to 1, only warn (instead of error) about missing ns imports */ |
44 | static bool allow_missing_ns_imports; |
45 | |
46 | static bool error_occurred; |
47 | |
48 | static bool ; |
49 | |
50 | /* |
51 | * Cut off the warnings when there are too many. This typically occurs when |
52 | * vmlinux is missing. ('make modules' without building vmlinux.) |
53 | */ |
54 | #define MAX_UNRESOLVED_REPORTS 10 |
55 | static unsigned int nr_unresolved; |
56 | |
57 | /* In kernel, this size is defined in linux/module.h; |
58 | * here we use Elf_Addr instead of long for covering cross-compile |
59 | */ |
60 | |
61 | #define MODULE_NAME_LEN (64 - sizeof(Elf_Addr)) |
62 | |
63 | void modpost_log(enum loglevel loglevel, const char *fmt, ...) |
64 | { |
65 | va_list arglist; |
66 | |
67 | switch (loglevel) { |
68 | case LOG_WARN: |
69 | fprintf(stderr, format: "WARNING: " ); |
70 | break; |
71 | case LOG_ERROR: |
72 | fprintf(stderr, format: "ERROR: " ); |
73 | error_occurred = true; |
74 | break; |
75 | default: /* invalid loglevel, ignore */ |
76 | break; |
77 | } |
78 | |
79 | fprintf(stderr, format: "modpost: " ); |
80 | |
81 | va_start(arglist, fmt); |
82 | vfprintf(stderr, format: fmt, arg: arglist); |
83 | va_end(arglist); |
84 | } |
85 | |
86 | static inline bool strends(const char *str, const char *postfix) |
87 | { |
88 | if (strlen(s: str) < strlen(s: postfix)) |
89 | return false; |
90 | |
91 | return strcmp(s1: str + strlen(s: str) - strlen(s: postfix), s2: postfix) == 0; |
92 | } |
93 | |
94 | void *do_nofail(void *ptr, const char *expr) |
95 | { |
96 | if (!ptr) |
97 | fatal("Memory allocation failure: %s.\n" , expr); |
98 | |
99 | return ptr; |
100 | } |
101 | |
102 | char *read_text_file(const char *filename) |
103 | { |
104 | struct stat st; |
105 | size_t nbytes; |
106 | int fd; |
107 | char *buf; |
108 | |
109 | fd = open(file: filename, O_RDONLY); |
110 | if (fd < 0) { |
111 | perror(s: filename); |
112 | exit(status: 1); |
113 | } |
114 | |
115 | if (fstat(fd: fd, buf: &st) < 0) { |
116 | perror(s: filename); |
117 | exit(status: 1); |
118 | } |
119 | |
120 | buf = NOFAIL(malloc(st.st_size + 1)); |
121 | |
122 | nbytes = st.st_size; |
123 | |
124 | while (nbytes) { |
125 | ssize_t bytes_read; |
126 | |
127 | bytes_read = read(fd: fd, buf: buf, nbytes: nbytes); |
128 | if (bytes_read < 0) { |
129 | perror(s: filename); |
130 | exit(status: 1); |
131 | } |
132 | |
133 | nbytes -= bytes_read; |
134 | } |
135 | buf[st.st_size] = '\0'; |
136 | |
137 | close(fd: fd); |
138 | |
139 | return buf; |
140 | } |
141 | |
142 | char *get_line(char **stringp) |
143 | { |
144 | char *orig = *stringp, *next; |
145 | |
146 | /* do not return the unwanted extra line at EOF */ |
147 | if (!orig || *orig == '\0') |
148 | return NULL; |
149 | |
150 | /* don't use strsep here, it is not available everywhere */ |
151 | next = strchr(s: orig, c: '\n'); |
152 | if (next) |
153 | *next++ = '\0'; |
154 | |
155 | *stringp = next; |
156 | |
157 | return orig; |
158 | } |
159 | |
160 | /* A list of all modules we processed */ |
161 | LIST_HEAD(modules); |
162 | |
163 | static struct module *find_module(const char *modname) |
164 | { |
165 | struct module *mod; |
166 | |
167 | list_for_each_entry(mod, &modules, list) { |
168 | if (strcmp(s1: mod->name, s2: modname) == 0) |
169 | return mod; |
170 | } |
171 | return NULL; |
172 | } |
173 | |
174 | static struct module *new_module(const char *name, size_t namelen) |
175 | { |
176 | struct module *mod; |
177 | |
178 | mod = NOFAIL(malloc(sizeof(*mod) + namelen + 1)); |
179 | memset(s: mod, c: 0, n: sizeof(*mod)); |
180 | |
181 | INIT_LIST_HEAD(list: &mod->exported_symbols); |
182 | INIT_LIST_HEAD(list: &mod->unresolved_symbols); |
183 | INIT_LIST_HEAD(list: &mod->missing_namespaces); |
184 | INIT_LIST_HEAD(list: &mod->imported_namespaces); |
185 | |
186 | memcpy(dest: mod->name, src: name, n: namelen); |
187 | mod->name[namelen] = '\0'; |
188 | mod->is_vmlinux = (strcmp(s1: mod->name, s2: "vmlinux" ) == 0); |
189 | |
190 | /* |
191 | * Set mod->is_gpl_compatible to true by default. If MODULE_LICENSE() |
192 | * is missing, do not check the use for EXPORT_SYMBOL_GPL() becasue |
193 | * modpost will exit wiht error anyway. |
194 | */ |
195 | mod->is_gpl_compatible = true; |
196 | |
197 | list_add_tail(new: &mod->list, head: &modules); |
198 | |
199 | return mod; |
200 | } |
201 | |
202 | /* A hash of all exported symbols, |
203 | * struct symbol is also used for lists of unresolved symbols */ |
204 | |
205 | #define SYMBOL_HASH_SIZE 1024 |
206 | |
207 | struct symbol { |
208 | struct symbol *next; |
209 | struct list_head list; /* link to module::exported_symbols or module::unresolved_symbols */ |
210 | struct module *module; |
211 | char *namespace; |
212 | unsigned int crc; |
213 | bool crc_valid; |
214 | bool weak; |
215 | bool is_func; |
216 | bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */ |
217 | bool used; /* there exists a user of this symbol */ |
218 | char name[]; |
219 | }; |
220 | |
221 | static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; |
222 | |
223 | /* This is based on the hash algorithm from gdbm, via tdb */ |
224 | static inline unsigned int tdb_hash(const char *name) |
225 | { |
226 | unsigned value; /* Used to compute the hash value. */ |
227 | unsigned i; /* Used to cycle through random values. */ |
228 | |
229 | /* Set the initial value from the key size. */ |
230 | for (value = 0x238F13AF * strlen(s: name), i = 0; name[i]; i++) |
231 | value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); |
232 | |
233 | return (1103515243 * value + 12345); |
234 | } |
235 | |
236 | /** |
237 | * Allocate a new symbols for use in the hash of exported symbols or |
238 | * the list of unresolved symbols per module |
239 | **/ |
240 | static struct symbol *alloc_symbol(const char *name) |
241 | { |
242 | struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); |
243 | |
244 | memset(s: s, c: 0, n: sizeof(*s)); |
245 | strcpy(dest: s->name, src: name); |
246 | |
247 | return s; |
248 | } |
249 | |
250 | /* For the hash of exported symbols */ |
251 | static void hash_add_symbol(struct symbol *sym) |
252 | { |
253 | unsigned int hash; |
254 | |
255 | hash = tdb_hash(name: sym->name) % SYMBOL_HASH_SIZE; |
256 | sym->next = symbolhash[hash]; |
257 | symbolhash[hash] = sym; |
258 | } |
259 | |
260 | static void sym_add_unresolved(const char *name, struct module *mod, bool weak) |
261 | { |
262 | struct symbol *sym; |
263 | |
264 | sym = alloc_symbol(name); |
265 | sym->weak = weak; |
266 | |
267 | list_add_tail(new: &sym->list, head: &mod->unresolved_symbols); |
268 | } |
269 | |
270 | static struct symbol *sym_find_with_module(const char *name, struct module *mod) |
271 | { |
272 | struct symbol *s; |
273 | |
274 | /* For our purposes, .foo matches foo. PPC64 needs this. */ |
275 | if (name[0] == '.') |
276 | name++; |
277 | |
278 | for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) { |
279 | if (strcmp(s1: s->name, s2: name) == 0 && (!mod || s->module == mod)) |
280 | return s; |
281 | } |
282 | return NULL; |
283 | } |
284 | |
285 | static struct symbol *find_symbol(const char *name) |
286 | { |
287 | return sym_find_with_module(name, NULL); |
288 | } |
289 | |
290 | struct namespace_list { |
291 | struct list_head list; |
292 | char namespace[]; |
293 | }; |
294 | |
295 | static bool contains_namespace(struct list_head *head, const char *namespace) |
296 | { |
297 | struct namespace_list *list; |
298 | |
299 | /* |
300 | * The default namespace is null string "", which is always implicitly |
301 | * contained. |
302 | */ |
303 | if (!namespace[0]) |
304 | return true; |
305 | |
306 | list_for_each_entry(list, head, list) { |
307 | if (!strcmp(s1: list->namespace, s2: namespace)) |
308 | return true; |
309 | } |
310 | |
311 | return false; |
312 | } |
313 | |
314 | static void add_namespace(struct list_head *head, const char *namespace) |
315 | { |
316 | struct namespace_list *ns_entry; |
317 | |
318 | if (!contains_namespace(head, namespace)) { |
319 | ns_entry = NOFAIL(malloc(sizeof(*ns_entry) + |
320 | strlen(namespace) + 1)); |
321 | strcpy(dest: ns_entry->namespace, src: namespace); |
322 | list_add_tail(new: &ns_entry->list, head); |
323 | } |
324 | } |
325 | |
326 | static void *sym_get_data_by_offset(const struct elf_info *info, |
327 | unsigned int secindex, unsigned long offset) |
328 | { |
329 | Elf_Shdr *sechdr = &info->sechdrs[secindex]; |
330 | |
331 | return (void *)info->hdr + sechdr->sh_offset + offset; |
332 | } |
333 | |
334 | void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) |
335 | { |
336 | return sym_get_data_by_offset(info, secindex: get_secindex(info, sym), |
337 | offset: sym->st_value); |
338 | } |
339 | |
340 | static const char *sech_name(const struct elf_info *info, Elf_Shdr *sechdr) |
341 | { |
342 | return sym_get_data_by_offset(info, secindex: info->secindex_strings, |
343 | offset: sechdr->sh_name); |
344 | } |
345 | |
346 | static const char *sec_name(const struct elf_info *info, unsigned int secindex) |
347 | { |
348 | /* |
349 | * If sym->st_shndx is a special section index, there is no |
350 | * corresponding section header. |
351 | * Return "" if the index is out of range of info->sechdrs[] array. |
352 | */ |
353 | if (secindex >= info->num_sections) |
354 | return "" ; |
355 | |
356 | return sech_name(info, sechdr: &info->sechdrs[secindex]); |
357 | } |
358 | |
359 | #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) |
360 | |
361 | static struct symbol *sym_add_exported(const char *name, struct module *mod, |
362 | bool gpl_only, const char *namespace) |
363 | { |
364 | struct symbol *s = find_symbol(name); |
365 | |
366 | if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) { |
367 | error("%s: '%s' exported twice. Previous export was in %s%s\n" , |
368 | mod->name, name, s->module->name, |
369 | s->module->is_vmlinux ? "" : ".ko" ); |
370 | } |
371 | |
372 | s = alloc_symbol(name); |
373 | s->module = mod; |
374 | s->is_gpl_only = gpl_only; |
375 | s->namespace = NOFAIL(strdup(namespace)); |
376 | list_add_tail(new: &s->list, head: &mod->exported_symbols); |
377 | hash_add_symbol(sym: s); |
378 | |
379 | return s; |
380 | } |
381 | |
382 | static void sym_set_crc(struct symbol *sym, unsigned int crc) |
383 | { |
384 | sym->crc = crc; |
385 | sym->crc_valid = true; |
386 | } |
387 | |
388 | static void *grab_file(const char *filename, size_t *size) |
389 | { |
390 | struct stat st; |
391 | void *map = MAP_FAILED; |
392 | int fd; |
393 | |
394 | fd = open(file: filename, O_RDONLY); |
395 | if (fd < 0) |
396 | return NULL; |
397 | if (fstat(fd: fd, buf: &st)) |
398 | goto failed; |
399 | |
400 | *size = st.st_size; |
401 | map = mmap(NULL, len: *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd: fd, offset: 0); |
402 | |
403 | failed: |
404 | close(fd: fd); |
405 | if (map == MAP_FAILED) |
406 | return NULL; |
407 | return map; |
408 | } |
409 | |
410 | static void release_file(void *file, size_t size) |
411 | { |
412 | munmap(addr: file, len: size); |
413 | } |
414 | |
415 | static int parse_elf(struct elf_info *info, const char *filename) |
416 | { |
417 | unsigned int i; |
418 | Elf_Ehdr *hdr; |
419 | Elf_Shdr *sechdrs; |
420 | Elf_Sym *sym; |
421 | const char *secstrings; |
422 | unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U; |
423 | |
424 | hdr = grab_file(filename, size: &info->size); |
425 | if (!hdr) { |
426 | if (ignore_missing_files) { |
427 | fprintf(stderr, format: "%s: %s (ignored)\n" , filename, |
428 | strerror(errno)); |
429 | return 0; |
430 | } |
431 | perror(s: filename); |
432 | exit(status: 1); |
433 | } |
434 | info->hdr = hdr; |
435 | if (info->size < sizeof(*hdr)) { |
436 | /* file too small, assume this is an empty .o file */ |
437 | return 0; |
438 | } |
439 | /* Is this a valid ELF file? */ |
440 | if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || |
441 | (hdr->e_ident[EI_MAG1] != ELFMAG1) || |
442 | (hdr->e_ident[EI_MAG2] != ELFMAG2) || |
443 | (hdr->e_ident[EI_MAG3] != ELFMAG3)) { |
444 | /* Not an ELF file - silently ignore it */ |
445 | return 0; |
446 | } |
447 | /* Fix endianness in ELF header */ |
448 | hdr->e_type = TO_NATIVE(hdr->e_type); |
449 | hdr->e_machine = TO_NATIVE(hdr->e_machine); |
450 | hdr->e_version = TO_NATIVE(hdr->e_version); |
451 | hdr->e_entry = TO_NATIVE(hdr->e_entry); |
452 | hdr->e_phoff = TO_NATIVE(hdr->e_phoff); |
453 | hdr->e_shoff = TO_NATIVE(hdr->e_shoff); |
454 | hdr->e_flags = TO_NATIVE(hdr->e_flags); |
455 | hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize); |
456 | hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize); |
457 | hdr->e_phnum = TO_NATIVE(hdr->e_phnum); |
458 | hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize); |
459 | hdr->e_shnum = TO_NATIVE(hdr->e_shnum); |
460 | hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); |
461 | sechdrs = (void *)hdr + hdr->e_shoff; |
462 | info->sechdrs = sechdrs; |
463 | |
464 | /* modpost only works for relocatable objects */ |
465 | if (hdr->e_type != ET_REL) |
466 | fatal("%s: not relocatable object." , filename); |
467 | |
468 | /* Check if file offset is correct */ |
469 | if (hdr->e_shoff > info->size) |
470 | fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n" , |
471 | (unsigned long)hdr->e_shoff, filename, info->size); |
472 | |
473 | if (hdr->e_shnum == SHN_UNDEF) { |
474 | /* |
475 | * There are more than 64k sections, |
476 | * read count from .sh_size. |
477 | */ |
478 | info->num_sections = TO_NATIVE(sechdrs[0].sh_size); |
479 | } |
480 | else { |
481 | info->num_sections = hdr->e_shnum; |
482 | } |
483 | if (hdr->e_shstrndx == SHN_XINDEX) { |
484 | info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link); |
485 | } |
486 | else { |
487 | info->secindex_strings = hdr->e_shstrndx; |
488 | } |
489 | |
490 | /* Fix endianness in section headers */ |
491 | for (i = 0; i < info->num_sections; i++) { |
492 | sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); |
493 | sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); |
494 | sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); |
495 | sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); |
496 | sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); |
497 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); |
498 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); |
499 | sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); |
500 | sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign); |
501 | sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); |
502 | } |
503 | /* Find symbol table. */ |
504 | secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset; |
505 | for (i = 1; i < info->num_sections; i++) { |
506 | const char *secname; |
507 | int nobits = sechdrs[i].sh_type == SHT_NOBITS; |
508 | |
509 | if (!nobits && sechdrs[i].sh_offset > info->size) |
510 | fatal("%s is truncated. sechdrs[i].sh_offset=%lu > sizeof(*hrd)=%zu\n" , |
511 | filename, (unsigned long)sechdrs[i].sh_offset, |
512 | sizeof(*hdr)); |
513 | |
514 | secname = secstrings + sechdrs[i].sh_name; |
515 | if (strcmp(s1: secname, s2: ".modinfo" ) == 0) { |
516 | if (nobits) |
517 | fatal("%s has NOBITS .modinfo\n" , filename); |
518 | info->modinfo = (void *)hdr + sechdrs[i].sh_offset; |
519 | info->modinfo_len = sechdrs[i].sh_size; |
520 | } else if (!strcmp(s1: secname, s2: ".export_symbol" )) { |
521 | info->export_symbol_secndx = i; |
522 | } |
523 | |
524 | if (sechdrs[i].sh_type == SHT_SYMTAB) { |
525 | unsigned int sh_link_idx; |
526 | symtab_idx = i; |
527 | info->symtab_start = (void *)hdr + |
528 | sechdrs[i].sh_offset; |
529 | info->symtab_stop = (void *)hdr + |
530 | sechdrs[i].sh_offset + sechdrs[i].sh_size; |
531 | sh_link_idx = sechdrs[i].sh_link; |
532 | info->strtab = (void *)hdr + |
533 | sechdrs[sh_link_idx].sh_offset; |
534 | } |
535 | |
536 | /* 32bit section no. table? ("more than 64k sections") */ |
537 | if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) { |
538 | symtab_shndx_idx = i; |
539 | info->symtab_shndx_start = (void *)hdr + |
540 | sechdrs[i].sh_offset; |
541 | info->symtab_shndx_stop = (void *)hdr + |
542 | sechdrs[i].sh_offset + sechdrs[i].sh_size; |
543 | } |
544 | } |
545 | if (!info->symtab_start) |
546 | fatal("%s has no symtab?\n" , filename); |
547 | |
548 | /* Fix endianness in symbols */ |
549 | for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { |
550 | sym->st_shndx = TO_NATIVE(sym->st_shndx); |
551 | sym->st_name = TO_NATIVE(sym->st_name); |
552 | sym->st_value = TO_NATIVE(sym->st_value); |
553 | sym->st_size = TO_NATIVE(sym->st_size); |
554 | } |
555 | |
556 | if (symtab_shndx_idx != ~0U) { |
557 | Elf32_Word *p; |
558 | if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link) |
559 | fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n" , |
560 | filename, sechdrs[symtab_shndx_idx].sh_link, |
561 | symtab_idx); |
562 | /* Fix endianness */ |
563 | for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; |
564 | p++) |
565 | *p = TO_NATIVE(*p); |
566 | } |
567 | |
568 | symsearch_init(elf: info); |
569 | |
570 | return 1; |
571 | } |
572 | |
573 | static void parse_elf_finish(struct elf_info *info) |
574 | { |
575 | symsearch_finish(elf: info); |
576 | release_file(file: info->hdr, size: info->size); |
577 | } |
578 | |
579 | static int ignore_undef_symbol(struct elf_info *info, const char *symname) |
580 | { |
581 | /* ignore __this_module, it will be resolved shortly */ |
582 | if (strcmp(s1: symname, s2: "__this_module" ) == 0) |
583 | return 1; |
584 | /* ignore global offset table */ |
585 | if (strcmp(s1: symname, s2: "_GLOBAL_OFFSET_TABLE_" ) == 0) |
586 | return 1; |
587 | if (info->hdr->e_machine == EM_PPC) |
588 | /* Special register function linked on all modules during final link of .ko */ |
589 | if (strstarts(symname, "_restgpr_" ) || |
590 | strstarts(symname, "_savegpr_" ) || |
591 | strstarts(symname, "_rest32gpr_" ) || |
592 | strstarts(symname, "_save32gpr_" ) || |
593 | strstarts(symname, "_restvr_" ) || |
594 | strstarts(symname, "_savevr_" )) |
595 | return 1; |
596 | if (info->hdr->e_machine == EM_PPC64) |
597 | /* Special register function linked on all modules during final link of .ko */ |
598 | if (strstarts(symname, "_restgpr0_" ) || |
599 | strstarts(symname, "_savegpr0_" ) || |
600 | strstarts(symname, "_restvr_" ) || |
601 | strstarts(symname, "_savevr_" ) || |
602 | strcmp(s1: symname, s2: ".TOC." ) == 0) |
603 | return 1; |
604 | |
605 | if (info->hdr->e_machine == EM_S390) |
606 | /* Expoline thunks are linked on all kernel modules during final link of .ko */ |
607 | if (strstarts(symname, "__s390_indirect_jump_r" )) |
608 | return 1; |
609 | /* Do not ignore this symbol */ |
610 | return 0; |
611 | } |
612 | |
613 | static void handle_symbol(struct module *mod, struct elf_info *info, |
614 | const Elf_Sym *sym, const char *symname) |
615 | { |
616 | switch (sym->st_shndx) { |
617 | case SHN_COMMON: |
618 | if (strstarts(symname, "__gnu_lto_" )) { |
619 | /* Should warn here, but modpost runs before the linker */ |
620 | } else |
621 | warn("\"%s\" [%s] is COMMON symbol\n" , symname, mod->name); |
622 | break; |
623 | case SHN_UNDEF: |
624 | /* undefined symbol */ |
625 | if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && |
626 | ELF_ST_BIND(sym->st_info) != STB_WEAK) |
627 | break; |
628 | if (ignore_undef_symbol(info, symname)) |
629 | break; |
630 | if (info->hdr->e_machine == EM_SPARC || |
631 | info->hdr->e_machine == EM_SPARCV9) { |
632 | /* Ignore register directives. */ |
633 | if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) |
634 | break; |
635 | if (symname[0] == '.') { |
636 | char *munged = NOFAIL(strdup(symname)); |
637 | munged[0] = '_'; |
638 | munged[1] = toupper(munged[1]); |
639 | symname = munged; |
640 | } |
641 | } |
642 | |
643 | sym_add_unresolved(name: symname, mod, |
644 | ELF_ST_BIND(sym->st_info) == STB_WEAK); |
645 | break; |
646 | default: |
647 | if (strcmp(s1: symname, s2: "init_module" ) == 0) |
648 | mod->has_init = true; |
649 | if (strcmp(s1: symname, s2: "cleanup_module" ) == 0) |
650 | mod->has_cleanup = true; |
651 | break; |
652 | } |
653 | } |
654 | |
655 | /** |
656 | * Parse tag=value strings from .modinfo section |
657 | **/ |
658 | static char *next_string(char *string, unsigned long *secsize) |
659 | { |
660 | /* Skip non-zero chars */ |
661 | while (string[0]) { |
662 | string++; |
663 | if ((*secsize)-- <= 1) |
664 | return NULL; |
665 | } |
666 | |
667 | /* Skip any zero padding. */ |
668 | while (!string[0]) { |
669 | string++; |
670 | if ((*secsize)-- <= 1) |
671 | return NULL; |
672 | } |
673 | return string; |
674 | } |
675 | |
676 | static char *get_next_modinfo(struct elf_info *info, const char *tag, |
677 | char *prev) |
678 | { |
679 | char *p; |
680 | unsigned int taglen = strlen(s: tag); |
681 | char *modinfo = info->modinfo; |
682 | unsigned long size = info->modinfo_len; |
683 | |
684 | if (prev) { |
685 | size -= prev - modinfo; |
686 | modinfo = next_string(string: prev, secsize: &size); |
687 | } |
688 | |
689 | for (p = modinfo; p; p = next_string(string: p, secsize: &size)) { |
690 | if (strncmp(s1: p, s2: tag, n: taglen) == 0 && p[taglen] == '=') |
691 | return p + taglen + 1; |
692 | } |
693 | return NULL; |
694 | } |
695 | |
696 | static char *get_modinfo(struct elf_info *info, const char *tag) |
697 | |
698 | { |
699 | return get_next_modinfo(info, tag, NULL); |
700 | } |
701 | |
702 | static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) |
703 | { |
704 | if (sym) |
705 | return elf->strtab + sym->st_name; |
706 | else |
707 | return "(unknown)" ; |
708 | } |
709 | |
710 | /* |
711 | * Check whether the 'string' argument matches one of the 'patterns', |
712 | * an array of shell wildcard patterns (glob). |
713 | * |
714 | * Return true is there is a match. |
715 | */ |
716 | static bool match(const char *string, const char *const patterns[]) |
717 | { |
718 | const char *pattern; |
719 | |
720 | while ((pattern = *patterns++)) { |
721 | if (!fnmatch(pattern: pattern, name: string, flags: 0)) |
722 | return true; |
723 | } |
724 | |
725 | return false; |
726 | } |
727 | |
728 | /* useful to pass patterns to match() directly */ |
729 | #define PATTERNS(...) \ |
730 | ({ \ |
731 | static const char *const patterns[] = {__VA_ARGS__, NULL}; \ |
732 | patterns; \ |
733 | }) |
734 | |
735 | /* sections that we do not want to do full section mismatch check on */ |
736 | static const char *const section_white_list[] = |
737 | { |
738 | ".comment*" , |
739 | ".debug*" , |
740 | ".zdebug*" , /* Compressed debug sections. */ |
741 | ".GCC.command.line" , /* record-gcc-switches */ |
742 | ".mdebug*" , /* alpha, score, mips etc. */ |
743 | ".pdr" , /* alpha, score, mips etc. */ |
744 | ".stab*" , |
745 | ".note*" , |
746 | ".got*" , |
747 | ".toc*" , |
748 | ".xt.prop" , /* xtensa */ |
749 | ".xt.lit" , /* xtensa */ |
750 | ".arcextmap*" , /* arc */ |
751 | ".gnu.linkonce.arcext*" , /* arc : modules */ |
752 | ".cmem*" , /* EZchip */ |
753 | ".fmt_slot*" , /* EZchip */ |
754 | ".gnu.lto*" , |
755 | ".discard.*" , |
756 | ".llvm.call-graph-profile" , /* call graph */ |
757 | NULL |
758 | }; |
759 | |
760 | /* |
761 | * This is used to find sections missing the SHF_ALLOC flag. |
762 | * The cause of this is often a section specified in assembler |
763 | * without "ax" / "aw". |
764 | */ |
765 | static void check_section(const char *modname, struct elf_info *elf, |
766 | Elf_Shdr *sechdr) |
767 | { |
768 | const char *sec = sech_name(info: elf, sechdr); |
769 | |
770 | if (sechdr->sh_type == SHT_PROGBITS && |
771 | !(sechdr->sh_flags & SHF_ALLOC) && |
772 | !match(string: sec, patterns: section_white_list)) { |
773 | warn("%s (%s): unexpected non-allocatable section.\n" |
774 | "Did you forget to use \"ax\"/\"aw\" in a .S file?\n" |
775 | "Note that for example <linux/init.h> contains\n" |
776 | "section definitions for use in .S files.\n\n" , |
777 | modname, sec); |
778 | } |
779 | } |
780 | |
781 | |
782 | |
783 | #define ALL_INIT_DATA_SECTIONS \ |
784 | ".init.setup", ".init.rodata", ".meminit.rodata", \ |
785 | ".init.data", ".meminit.data" |
786 | |
787 | #define ALL_PCI_INIT_SECTIONS \ |
788 | ".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \ |
789 | ".pci_fixup_enable", ".pci_fixup_resume", \ |
790 | ".pci_fixup_resume_early", ".pci_fixup_suspend" |
791 | |
792 | #define ALL_XXXINIT_SECTIONS ".meminit.*" |
793 | |
794 | #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS |
795 | #define ALL_EXIT_SECTIONS ".exit.*" |
796 | |
797 | #define DATA_SECTIONS ".data", ".data.rel" |
798 | #define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \ |
799 | ".kprobes.text", ".cpuidle.text", ".noinstr.text", \ |
800 | ".ltext", ".ltext.*" |
801 | #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ |
802 | ".fixup", ".entry.text", ".exception.text", \ |
803 | ".coldtext", ".softirqentry.text" |
804 | |
805 | #define INIT_SECTIONS ".init.*" |
806 | |
807 | #define ALL_TEXT_SECTIONS ".init.text", ".meminit.text", ".exit.text", \ |
808 | TEXT_SECTIONS, OTHER_TEXT_SECTIONS |
809 | |
810 | enum mismatch { |
811 | TEXTDATA_TO_ANY_INIT_EXIT, |
812 | XXXINIT_TO_SOME_INIT, |
813 | ANY_INIT_TO_ANY_EXIT, |
814 | ANY_EXIT_TO_ANY_INIT, |
815 | EXTABLE_TO_NON_TEXT, |
816 | }; |
817 | |
818 | /** |
819 | * Describe how to match sections on different criteria: |
820 | * |
821 | * @fromsec: Array of sections to be matched. |
822 | * |
823 | * @bad_tosec: Relocations applied to a section in @fromsec to a section in |
824 | * this array is forbidden (black-list). Can be empty. |
825 | * |
826 | * @good_tosec: Relocations applied to a section in @fromsec must be |
827 | * targeting sections in this array (white-list). Can be empty. |
828 | * |
829 | * @mismatch: Type of mismatch. |
830 | */ |
831 | struct sectioncheck { |
832 | const char *fromsec[20]; |
833 | const char *bad_tosec[20]; |
834 | const char *good_tosec[20]; |
835 | enum mismatch mismatch; |
836 | }; |
837 | |
838 | static const struct sectioncheck sectioncheck[] = { |
839 | /* Do not reference init/exit code/data from |
840 | * normal code and data |
841 | */ |
842 | { |
843 | .fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL }, |
844 | .bad_tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }, |
845 | .mismatch = TEXTDATA_TO_ANY_INIT_EXIT, |
846 | }, |
847 | /* Do not reference init code/data from meminit code/data */ |
848 | { |
849 | .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, |
850 | .bad_tosec = { INIT_SECTIONS, NULL }, |
851 | .mismatch = XXXINIT_TO_SOME_INIT, |
852 | }, |
853 | /* Do not use exit code/data from init code */ |
854 | { |
855 | .fromsec = { ALL_INIT_SECTIONS, NULL }, |
856 | .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, |
857 | .mismatch = ANY_INIT_TO_ANY_EXIT, |
858 | }, |
859 | /* Do not use init code/data from exit code */ |
860 | { |
861 | .fromsec = { ALL_EXIT_SECTIONS, NULL }, |
862 | .bad_tosec = { ALL_INIT_SECTIONS, NULL }, |
863 | .mismatch = ANY_EXIT_TO_ANY_INIT, |
864 | }, |
865 | { |
866 | .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, |
867 | .bad_tosec = { INIT_SECTIONS, NULL }, |
868 | .mismatch = ANY_INIT_TO_ANY_EXIT, |
869 | }, |
870 | { |
871 | .fromsec = { "__ex_table" , NULL }, |
872 | /* If you're adding any new black-listed sections in here, consider |
873 | * adding a special 'printer' for them in scripts/check_extable. |
874 | */ |
875 | .bad_tosec = { ".altinstr_replacement" , NULL }, |
876 | .good_tosec = {ALL_TEXT_SECTIONS , NULL}, |
877 | .mismatch = EXTABLE_TO_NON_TEXT, |
878 | } |
879 | }; |
880 | |
881 | static const struct sectioncheck *section_mismatch( |
882 | const char *fromsec, const char *tosec) |
883 | { |
884 | int i; |
885 | |
886 | /* |
887 | * The target section could be the SHT_NUL section when we're |
888 | * handling relocations to un-resolved symbols, trying to match it |
889 | * doesn't make much sense and causes build failures on parisc |
890 | * architectures. |
891 | */ |
892 | if (*tosec == '\0') |
893 | return NULL; |
894 | |
895 | for (i = 0; i < ARRAY_SIZE(sectioncheck); i++) { |
896 | const struct sectioncheck *check = §ioncheck[i]; |
897 | |
898 | if (match(string: fromsec, patterns: check->fromsec)) { |
899 | if (check->bad_tosec[0] && match(string: tosec, patterns: check->bad_tosec)) |
900 | return check; |
901 | if (check->good_tosec[0] && !match(string: tosec, patterns: check->good_tosec)) |
902 | return check; |
903 | } |
904 | } |
905 | return NULL; |
906 | } |
907 | |
908 | /** |
909 | * Whitelist to allow certain references to pass with no warning. |
910 | * |
911 | * Pattern 1: |
912 | * If a module parameter is declared __initdata and permissions=0 |
913 | * then this is legal despite the warning generated. |
914 | * We cannot see value of permissions here, so just ignore |
915 | * this pattern. |
916 | * The pattern is identified by: |
917 | * tosec = .init.data |
918 | * fromsec = .data* |
919 | * atsym =__param* |
920 | * |
921 | * Pattern 1a: |
922 | * module_param_call() ops can refer to __init set function if permissions=0 |
923 | * The pattern is identified by: |
924 | * tosec = .init.text |
925 | * fromsec = .data* |
926 | * atsym = __param_ops_* |
927 | * |
928 | * Pattern 3: |
929 | * Whitelist all references from .head.text to any init section |
930 | * |
931 | * Pattern 4: |
932 | * Some symbols belong to init section but still it is ok to reference |
933 | * these from non-init sections as these symbols don't have any memory |
934 | * allocated for them and symbol address and value are same. So even |
935 | * if init section is freed, its ok to reference those symbols. |
936 | * For ex. symbols marking the init section boundaries. |
937 | * This pattern is identified by |
938 | * refsymname = __init_begin, _sinittext, _einittext |
939 | * |
940 | * Pattern 5: |
941 | * GCC may optimize static inlines when fed constant arg(s) resulting |
942 | * in functions like cpumask_empty() -- generating an associated symbol |
943 | * cpumask_empty.constprop.3 that appears in the audit. If the const that |
944 | * is passed in comes from __init, like say nmi_ipi_mask, we get a |
945 | * meaningless section warning. May need to add isra symbols too... |
946 | * This pattern is identified by |
947 | * tosec = init section |
948 | * fromsec = text section |
949 | * refsymname = *.constprop.* |
950 | * |
951 | **/ |
952 | static int secref_whitelist(const char *fromsec, const char *fromsym, |
953 | const char *tosec, const char *tosym) |
954 | { |
955 | /* Check for pattern 1 */ |
956 | if (match(string: tosec, PATTERNS(ALL_INIT_DATA_SECTIONS)) && |
957 | match(string: fromsec, PATTERNS(DATA_SECTIONS)) && |
958 | strstarts(fromsym, "__param" )) |
959 | return 0; |
960 | |
961 | /* Check for pattern 1a */ |
962 | if (strcmp(s1: tosec, s2: ".init.text" ) == 0 && |
963 | match(string: fromsec, PATTERNS(DATA_SECTIONS)) && |
964 | strstarts(fromsym, "__param_ops_" )) |
965 | return 0; |
966 | |
967 | /* symbols in data sections that may refer to any init/exit sections */ |
968 | if (match(string: fromsec, PATTERNS(DATA_SECTIONS)) && |
969 | match(string: tosec, PATTERNS(ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS)) && |
970 | match(string: fromsym, PATTERNS("*_ops" , "*_probe" , "*_console" ))) |
971 | return 0; |
972 | |
973 | /* |
974 | * symbols in data sections must not refer to .exit.*, but there are |
975 | * quite a few offenders, so hide these unless for W=1 builds until |
976 | * these are fixed. |
977 | */ |
978 | if (!extra_warn && |
979 | match(string: fromsec, PATTERNS(DATA_SECTIONS)) && |
980 | match(string: tosec, PATTERNS(ALL_EXIT_SECTIONS)) && |
981 | match(string: fromsym, PATTERNS("*driver" ))) |
982 | return 0; |
983 | |
984 | /* Check for pattern 3 */ |
985 | if (strstarts(fromsec, ".head.text" ) && |
986 | match(string: tosec, PATTERNS(ALL_INIT_SECTIONS))) |
987 | return 0; |
988 | |
989 | /* Check for pattern 4 */ |
990 | if (match(string: tosym, PATTERNS("__init_begin" , "_sinittext" , "_einittext" ))) |
991 | return 0; |
992 | |
993 | /* Check for pattern 5 */ |
994 | if (match(string: fromsec, PATTERNS(ALL_TEXT_SECTIONS)) && |
995 | match(string: tosec, PATTERNS(ALL_INIT_SECTIONS)) && |
996 | match(string: fromsym, PATTERNS("*.constprop.*" ))) |
997 | return 0; |
998 | |
999 | return 1; |
1000 | } |
1001 | |
1002 | static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr, |
1003 | unsigned int secndx) |
1004 | { |
1005 | return symsearch_find_nearest(elf, addr, secndx, false, min_distance: ~0); |
1006 | } |
1007 | |
1008 | static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym) |
1009 | { |
1010 | Elf_Sym *new_sym; |
1011 | |
1012 | /* If the supplied symbol has a valid name, return it */ |
1013 | if (is_valid_name(elf, sym)) |
1014 | return sym; |
1015 | |
1016 | /* |
1017 | * Strive to find a better symbol name, but the resulting name may not |
1018 | * match the symbol referenced in the original code. |
1019 | */ |
1020 | new_sym = symsearch_find_nearest(elf, addr, secndx: get_secindex(info: elf, sym), |
1021 | true, min_distance: 20); |
1022 | return new_sym ? new_sym : sym; |
1023 | } |
1024 | |
1025 | static bool is_executable_section(struct elf_info *elf, unsigned int secndx) |
1026 | { |
1027 | if (secndx >= elf->num_sections) |
1028 | return false; |
1029 | |
1030 | return (elf->sechdrs[secndx].sh_flags & SHF_EXECINSTR) != 0; |
1031 | } |
1032 | |
1033 | static void default_mismatch_handler(const char *modname, struct elf_info *elf, |
1034 | const struct sectioncheck* const mismatch, |
1035 | Elf_Sym *tsym, |
1036 | unsigned int fsecndx, const char *fromsec, Elf_Addr faddr, |
1037 | const char *tosec, Elf_Addr taddr) |
1038 | { |
1039 | Elf_Sym *from; |
1040 | const char *tosym; |
1041 | const char *fromsym; |
1042 | |
1043 | from = find_fromsym(elf, addr: faddr, secndx: fsecndx); |
1044 | fromsym = sym_name(elf, sym: from); |
1045 | |
1046 | tsym = find_tosym(elf, addr: taddr, sym: tsym); |
1047 | tosym = sym_name(elf, sym: tsym); |
1048 | |
1049 | /* check whitelist - we may ignore it */ |
1050 | if (!secref_whitelist(fromsec, fromsym, tosec, tosym)) |
1051 | return; |
1052 | |
1053 | sec_mismatch_count++; |
1054 | |
1055 | warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n" , |
1056 | modname, fromsym, |
1057 | (unsigned int)(faddr - (from ? from->st_value : 0)), |
1058 | fromsec, tosym, tosec); |
1059 | |
1060 | if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) { |
1061 | if (match(string: tosec, patterns: mismatch->bad_tosec)) |
1062 | fatal("The relocation at %s+0x%lx references\n" |
1063 | "section \"%s\" which is black-listed.\n" |
1064 | "Something is seriously wrong and should be fixed.\n" |
1065 | "You might get more information about where this is\n" |
1066 | "coming from by using scripts/check_extable.sh %s\n" , |
1067 | fromsec, (long)faddr, tosec, modname); |
1068 | else if (is_executable_section(elf, secndx: get_secindex(info: elf, sym: tsym))) |
1069 | warn("The relocation at %s+0x%lx references\n" |
1070 | "section \"%s\" which is not in the list of\n" |
1071 | "authorized sections. If you're adding a new section\n" |
1072 | "and/or if this reference is valid, add \"%s\" to the\n" |
1073 | "list of authorized sections to jump to on fault.\n" |
1074 | "This can be achieved by adding \"%s\" to\n" |
1075 | "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n" , |
1076 | fromsec, (long)faddr, tosec, tosec, tosec); |
1077 | else |
1078 | error("%s+0x%lx references non-executable section '%s'\n" , |
1079 | fromsec, (long)faddr, tosec); |
1080 | } |
1081 | } |
1082 | |
1083 | static void check_export_symbol(struct module *mod, struct elf_info *elf, |
1084 | Elf_Addr faddr, const char *secname, |
1085 | Elf_Sym *sym) |
1086 | { |
1087 | static const char *prefix = "__export_symbol_" ; |
1088 | const char *label_name, *name, *data; |
1089 | Elf_Sym *label; |
1090 | struct symbol *s; |
1091 | bool is_gpl; |
1092 | |
1093 | label = find_fromsym(elf, addr: faddr, secndx: elf->export_symbol_secndx); |
1094 | label_name = sym_name(elf, sym: label); |
1095 | |
1096 | if (!strstarts(label_name, prefix)) { |
1097 | error("%s: .export_symbol section contains strange symbol '%s'\n" , |
1098 | mod->name, label_name); |
1099 | return; |
1100 | } |
1101 | |
1102 | if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && |
1103 | ELF_ST_BIND(sym->st_info) != STB_WEAK) { |
1104 | error("%s: local symbol '%s' was exported\n" , mod->name, |
1105 | label_name + strlen(prefix)); |
1106 | return; |
1107 | } |
1108 | |
1109 | name = sym_name(elf, sym); |
1110 | if (strcmp(s1: label_name + strlen(s: prefix), s2: name)) { |
1111 | error("%s: .export_symbol section references '%s', but it does not seem to be an export symbol\n" , |
1112 | mod->name, name); |
1113 | return; |
1114 | } |
1115 | |
1116 | data = sym_get_data(info: elf, sym: label); /* license */ |
1117 | if (!strcmp(s1: data, s2: "GPL" )) { |
1118 | is_gpl = true; |
1119 | } else if (!strcmp(s1: data, s2: "" )) { |
1120 | is_gpl = false; |
1121 | } else { |
1122 | error("%s: unknown license '%s' was specified for '%s'\n" , |
1123 | mod->name, data, name); |
1124 | return; |
1125 | } |
1126 | |
1127 | data += strlen(s: data) + 1; /* namespace */ |
1128 | s = sym_add_exported(name, mod, gpl_only: is_gpl, namespace: data); |
1129 | |
1130 | /* |
1131 | * We need to be aware whether we are exporting a function or |
1132 | * a data on some architectures. |
1133 | */ |
1134 | s->is_func = (ELF_ST_TYPE(sym->st_info) == STT_FUNC); |
1135 | |
1136 | /* |
1137 | * For parisc64, symbols prefixed $$ from the library have the symbol type |
1138 | * STT_LOPROC. They should be handled as functions too. |
1139 | */ |
1140 | if (elf->hdr->e_ident[EI_CLASS] == ELFCLASS64 && |
1141 | elf->hdr->e_machine == EM_PARISC && |
1142 | ELF_ST_TYPE(sym->st_info) == STT_LOPROC) |
1143 | s->is_func = true; |
1144 | |
1145 | if (match(string: secname, PATTERNS(ALL_INIT_SECTIONS))) |
1146 | warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n" , |
1147 | mod->name, name); |
1148 | else if (match(string: secname, PATTERNS(ALL_EXIT_SECTIONS))) |
1149 | warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n" , |
1150 | mod->name, name); |
1151 | } |
1152 | |
1153 | static void check_section_mismatch(struct module *mod, struct elf_info *elf, |
1154 | Elf_Sym *sym, |
1155 | unsigned int fsecndx, const char *fromsec, |
1156 | Elf_Addr faddr, Elf_Addr taddr) |
1157 | { |
1158 | const char *tosec = sec_name(info: elf, secindex: get_secindex(info: elf, sym)); |
1159 | const struct sectioncheck *mismatch; |
1160 | |
1161 | if (module_enabled && elf->export_symbol_secndx == fsecndx) { |
1162 | check_export_symbol(mod, elf, faddr, secname: tosec, sym); |
1163 | return; |
1164 | } |
1165 | |
1166 | mismatch = section_mismatch(fromsec, tosec); |
1167 | if (!mismatch) |
1168 | return; |
1169 | |
1170 | default_mismatch_handler(modname: mod->name, elf, mismatch, tsym: sym, |
1171 | fsecndx, fromsec, faddr, |
1172 | tosec, taddr); |
1173 | } |
1174 | |
1175 | static Elf_Addr addend_386_rel(uint32_t *location, unsigned int r_type) |
1176 | { |
1177 | switch (r_type) { |
1178 | case R_386_32: |
1179 | return TO_NATIVE(*location); |
1180 | case R_386_PC32: |
1181 | return TO_NATIVE(*location) + 4; |
1182 | } |
1183 | |
1184 | return (Elf_Addr)(-1); |
1185 | } |
1186 | |
1187 | #ifndef R_ARM_CALL |
1188 | #define R_ARM_CALL 28 |
1189 | #endif |
1190 | #ifndef R_ARM_JUMP24 |
1191 | #define R_ARM_JUMP24 29 |
1192 | #endif |
1193 | |
1194 | #ifndef R_ARM_THM_CALL |
1195 | #define R_ARM_THM_CALL 10 |
1196 | #endif |
1197 | #ifndef R_ARM_THM_JUMP24 |
1198 | #define R_ARM_THM_JUMP24 30 |
1199 | #endif |
1200 | |
1201 | #ifndef R_ARM_MOVW_ABS_NC |
1202 | #define R_ARM_MOVW_ABS_NC 43 |
1203 | #endif |
1204 | |
1205 | #ifndef R_ARM_MOVT_ABS |
1206 | #define R_ARM_MOVT_ABS 44 |
1207 | #endif |
1208 | |
1209 | #ifndef R_ARM_THM_MOVW_ABS_NC |
1210 | #define R_ARM_THM_MOVW_ABS_NC 47 |
1211 | #endif |
1212 | |
1213 | #ifndef R_ARM_THM_MOVT_ABS |
1214 | #define R_ARM_THM_MOVT_ABS 48 |
1215 | #endif |
1216 | |
1217 | #ifndef R_ARM_THM_JUMP19 |
1218 | #define R_ARM_THM_JUMP19 51 |
1219 | #endif |
1220 | |
1221 | static int32_t sign_extend32(int32_t value, int index) |
1222 | { |
1223 | uint8_t shift = 31 - index; |
1224 | |
1225 | return (int32_t)(value << shift) >> shift; |
1226 | } |
1227 | |
1228 | static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type) |
1229 | { |
1230 | uint32_t inst, upper, lower, sign, j1, j2; |
1231 | int32_t offset; |
1232 | |
1233 | switch (r_type) { |
1234 | case R_ARM_ABS32: |
1235 | case R_ARM_REL32: |
1236 | inst = TO_NATIVE(*(uint32_t *)loc); |
1237 | return inst + sym->st_value; |
1238 | case R_ARM_MOVW_ABS_NC: |
1239 | case R_ARM_MOVT_ABS: |
1240 | inst = TO_NATIVE(*(uint32_t *)loc); |
1241 | offset = sign_extend32(value: ((inst & 0xf0000) >> 4) | (inst & 0xfff), |
1242 | index: 15); |
1243 | return offset + sym->st_value; |
1244 | case R_ARM_PC24: |
1245 | case R_ARM_CALL: |
1246 | case R_ARM_JUMP24: |
1247 | inst = TO_NATIVE(*(uint32_t *)loc); |
1248 | offset = sign_extend32(value: (inst & 0x00ffffff) << 2, index: 25); |
1249 | return offset + sym->st_value + 8; |
1250 | case R_ARM_THM_MOVW_ABS_NC: |
1251 | case R_ARM_THM_MOVT_ABS: |
1252 | upper = TO_NATIVE(*(uint16_t *)loc); |
1253 | lower = TO_NATIVE(*((uint16_t *)loc + 1)); |
1254 | offset = sign_extend32(value: ((upper & 0x000f) << 12) | |
1255 | ((upper & 0x0400) << 1) | |
1256 | ((lower & 0x7000) >> 4) | |
1257 | (lower & 0x00ff), |
1258 | index: 15); |
1259 | return offset + sym->st_value; |
1260 | case R_ARM_THM_JUMP19: |
1261 | /* |
1262 | * Encoding T3: |
1263 | * S = upper[10] |
1264 | * imm6 = upper[5:0] |
1265 | * J1 = lower[13] |
1266 | * J2 = lower[11] |
1267 | * imm11 = lower[10:0] |
1268 | * imm32 = SignExtend(S:J2:J1:imm6:imm11:'0') |
1269 | */ |
1270 | upper = TO_NATIVE(*(uint16_t *)loc); |
1271 | lower = TO_NATIVE(*((uint16_t *)loc + 1)); |
1272 | |
1273 | sign = (upper >> 10) & 1; |
1274 | j1 = (lower >> 13) & 1; |
1275 | j2 = (lower >> 11) & 1; |
1276 | offset = sign_extend32(value: (sign << 20) | (j2 << 19) | (j1 << 18) | |
1277 | ((upper & 0x03f) << 12) | |
1278 | ((lower & 0x07ff) << 1), |
1279 | index: 20); |
1280 | return offset + sym->st_value + 4; |
1281 | case R_ARM_THM_CALL: |
1282 | case R_ARM_THM_JUMP24: |
1283 | /* |
1284 | * Encoding T4: |
1285 | * S = upper[10] |
1286 | * imm10 = upper[9:0] |
1287 | * J1 = lower[13] |
1288 | * J2 = lower[11] |
1289 | * imm11 = lower[10:0] |
1290 | * I1 = NOT(J1 XOR S) |
1291 | * I2 = NOT(J2 XOR S) |
1292 | * imm32 = SignExtend(S:I1:I2:imm10:imm11:'0') |
1293 | */ |
1294 | upper = TO_NATIVE(*(uint16_t *)loc); |
1295 | lower = TO_NATIVE(*((uint16_t *)loc + 1)); |
1296 | |
1297 | sign = (upper >> 10) & 1; |
1298 | j1 = (lower >> 13) & 1; |
1299 | j2 = (lower >> 11) & 1; |
1300 | offset = sign_extend32(value: (sign << 24) | |
1301 | ((~(j1 ^ sign) & 1) << 23) | |
1302 | ((~(j2 ^ sign) & 1) << 22) | |
1303 | ((upper & 0x03ff) << 12) | |
1304 | ((lower & 0x07ff) << 1), |
1305 | index: 24); |
1306 | return offset + sym->st_value + 4; |
1307 | } |
1308 | |
1309 | return (Elf_Addr)(-1); |
1310 | } |
1311 | |
1312 | static Elf_Addr addend_mips_rel(uint32_t *location, unsigned int r_type) |
1313 | { |
1314 | uint32_t inst; |
1315 | |
1316 | inst = TO_NATIVE(*location); |
1317 | switch (r_type) { |
1318 | case R_MIPS_LO16: |
1319 | return inst & 0xffff; |
1320 | case R_MIPS_26: |
1321 | return (inst & 0x03ffffff) << 2; |
1322 | case R_MIPS_32: |
1323 | return inst; |
1324 | } |
1325 | return (Elf_Addr)(-1); |
1326 | } |
1327 | |
1328 | #ifndef EM_RISCV |
1329 | #define EM_RISCV 243 |
1330 | #endif |
1331 | |
1332 | #ifndef R_RISCV_SUB32 |
1333 | #define R_RISCV_SUB32 39 |
1334 | #endif |
1335 | |
1336 | #ifndef EM_LOONGARCH |
1337 | #define EM_LOONGARCH 258 |
1338 | #endif |
1339 | |
1340 | #ifndef R_LARCH_SUB32 |
1341 | #define R_LARCH_SUB32 55 |
1342 | #endif |
1343 | |
1344 | #ifndef R_LARCH_RELAX |
1345 | #define R_LARCH_RELAX 100 |
1346 | #endif |
1347 | |
1348 | #ifndef R_LARCH_ALIGN |
1349 | #define R_LARCH_ALIGN 102 |
1350 | #endif |
1351 | |
1352 | static void get_rel_type_and_sym(struct elf_info *elf, uint64_t r_info, |
1353 | unsigned int *r_type, unsigned int *r_sym) |
1354 | { |
1355 | typedef struct { |
1356 | Elf64_Word r_sym; /* Symbol index */ |
1357 | unsigned char r_ssym; /* Special symbol for 2nd relocation */ |
1358 | unsigned char r_type3; /* 3rd relocation type */ |
1359 | unsigned char r_type2; /* 2nd relocation type */ |
1360 | unsigned char r_type; /* 1st relocation type */ |
1361 | } Elf64_Mips_R_Info; |
1362 | |
1363 | bool is_64bit = (elf->hdr->e_ident[EI_CLASS] == ELFCLASS64); |
1364 | |
1365 | if (elf->hdr->e_machine == EM_MIPS && is_64bit) { |
1366 | Elf64_Mips_R_Info *mips64_r_info = (void *)&r_info; |
1367 | |
1368 | *r_type = mips64_r_info->r_type; |
1369 | *r_sym = TO_NATIVE(mips64_r_info->r_sym); |
1370 | return; |
1371 | } |
1372 | |
1373 | if (is_64bit) |
1374 | r_info = TO_NATIVE((Elf64_Xword)r_info); |
1375 | else |
1376 | r_info = TO_NATIVE((Elf32_Word)r_info); |
1377 | |
1378 | *r_type = ELF_R_TYPE(r_info); |
1379 | *r_sym = ELF_R_SYM(r_info); |
1380 | } |
1381 | |
1382 | static void section_rela(struct module *mod, struct elf_info *elf, |
1383 | unsigned int fsecndx, const char *fromsec, |
1384 | const Elf_Rela *start, const Elf_Rela *stop) |
1385 | { |
1386 | const Elf_Rela *rela; |
1387 | |
1388 | for (rela = start; rela < stop; rela++) { |
1389 | Elf_Sym *tsym; |
1390 | Elf_Addr taddr, r_offset; |
1391 | unsigned int r_type, r_sym; |
1392 | |
1393 | r_offset = TO_NATIVE(rela->r_offset); |
1394 | get_rel_type_and_sym(elf, r_info: rela->r_info, r_type: &r_type, r_sym: &r_sym); |
1395 | |
1396 | tsym = elf->symtab_start + r_sym; |
1397 | taddr = tsym->st_value + TO_NATIVE(rela->r_addend); |
1398 | |
1399 | switch (elf->hdr->e_machine) { |
1400 | case EM_RISCV: |
1401 | if (!strcmp(s1: "__ex_table" , s2: fromsec) && |
1402 | r_type == R_RISCV_SUB32) |
1403 | continue; |
1404 | break; |
1405 | case EM_LOONGARCH: |
1406 | switch (r_type) { |
1407 | case R_LARCH_SUB32: |
1408 | if (!strcmp(s1: "__ex_table" , s2: fromsec)) |
1409 | continue; |
1410 | break; |
1411 | case R_LARCH_RELAX: |
1412 | case R_LARCH_ALIGN: |
1413 | /* These relocs do not refer to symbols */ |
1414 | continue; |
1415 | } |
1416 | break; |
1417 | } |
1418 | |
1419 | check_section_mismatch(mod, elf, sym: tsym, |
1420 | fsecndx, fromsec, faddr: r_offset, taddr); |
1421 | } |
1422 | } |
1423 | |
1424 | static void section_rel(struct module *mod, struct elf_info *elf, |
1425 | unsigned int fsecndx, const char *fromsec, |
1426 | const Elf_Rel *start, const Elf_Rel *stop) |
1427 | { |
1428 | const Elf_Rel *rel; |
1429 | |
1430 | for (rel = start; rel < stop; rel++) { |
1431 | Elf_Sym *tsym; |
1432 | Elf_Addr taddr, r_offset; |
1433 | unsigned int r_type, r_sym; |
1434 | void *loc; |
1435 | |
1436 | r_offset = TO_NATIVE(rel->r_offset); |
1437 | get_rel_type_and_sym(elf, r_info: rel->r_info, r_type: &r_type, r_sym: &r_sym); |
1438 | |
1439 | loc = sym_get_data_by_offset(info: elf, secindex: fsecndx, offset: r_offset); |
1440 | tsym = elf->symtab_start + r_sym; |
1441 | |
1442 | switch (elf->hdr->e_machine) { |
1443 | case EM_386: |
1444 | taddr = addend_386_rel(location: loc, r_type); |
1445 | break; |
1446 | case EM_ARM: |
1447 | taddr = addend_arm_rel(loc, sym: tsym, r_type); |
1448 | break; |
1449 | case EM_MIPS: |
1450 | taddr = addend_mips_rel(location: loc, r_type); |
1451 | break; |
1452 | default: |
1453 | fatal("Please add code to calculate addend for this architecture\n" ); |
1454 | } |
1455 | |
1456 | check_section_mismatch(mod, elf, sym: tsym, |
1457 | fsecndx, fromsec, faddr: r_offset, taddr); |
1458 | } |
1459 | } |
1460 | |
1461 | /** |
1462 | * A module includes a number of sections that are discarded |
1463 | * either when loaded or when used as built-in. |
1464 | * For loaded modules all functions marked __init and all data |
1465 | * marked __initdata will be discarded when the module has been initialized. |
1466 | * Likewise for modules used built-in the sections marked __exit |
1467 | * are discarded because __exit marked function are supposed to be called |
1468 | * only when a module is unloaded which never happens for built-in modules. |
1469 | * The check_sec_ref() function traverses all relocation records |
1470 | * to find all references to a section that reference a section that will |
1471 | * be discarded and warns about it. |
1472 | **/ |
1473 | static void check_sec_ref(struct module *mod, struct elf_info *elf) |
1474 | { |
1475 | int i; |
1476 | |
1477 | /* Walk through all sections */ |
1478 | for (i = 0; i < elf->num_sections; i++) { |
1479 | Elf_Shdr *sechdr = &elf->sechdrs[i]; |
1480 | |
1481 | check_section(modname: mod->name, elf, sechdr); |
1482 | /* We want to process only relocation sections and not .init */ |
1483 | if (sechdr->sh_type == SHT_REL || sechdr->sh_type == SHT_RELA) { |
1484 | /* section to which the relocation applies */ |
1485 | unsigned int secndx = sechdr->sh_info; |
1486 | const char *secname = sec_name(info: elf, secindex: secndx); |
1487 | const void *start, *stop; |
1488 | |
1489 | /* If the section is known good, skip it */ |
1490 | if (match(string: secname, patterns: section_white_list)) |
1491 | continue; |
1492 | |
1493 | start = sym_get_data_by_offset(info: elf, secindex: i, offset: 0); |
1494 | stop = start + sechdr->sh_size; |
1495 | |
1496 | if (sechdr->sh_type == SHT_RELA) |
1497 | section_rela(mod, elf, fsecndx: secndx, fromsec: secname, |
1498 | start, stop); |
1499 | else |
1500 | section_rel(mod, elf, fsecndx: secndx, fromsec: secname, |
1501 | start, stop); |
1502 | } |
1503 | } |
1504 | } |
1505 | |
1506 | static char *remove_dot(char *s) |
1507 | { |
1508 | size_t n = strcspn(s: s, reject: "." ); |
1509 | |
1510 | if (n && s[n]) { |
1511 | size_t m = strspn(s: s + n + 1, accept: "0123456789" ); |
1512 | if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0)) |
1513 | s[n] = 0; |
1514 | } |
1515 | return s; |
1516 | } |
1517 | |
1518 | /* |
1519 | * The CRCs are recorded in .*.cmd files in the form of: |
1520 | * #SYMVER <name> <crc> |
1521 | */ |
1522 | static void (const char *object, struct module *mod) |
1523 | { |
1524 | char cmd_file[PATH_MAX]; |
1525 | char *buf, *p; |
1526 | const char *base; |
1527 | int dirlen, ret; |
1528 | |
1529 | base = strrchr(s: object, c: '/'); |
1530 | if (base) { |
1531 | base++; |
1532 | dirlen = base - object; |
1533 | } else { |
1534 | dirlen = 0; |
1535 | base = object; |
1536 | } |
1537 | |
1538 | ret = snprintf(s: cmd_file, maxlen: sizeof(cmd_file), format: "%.*s.%s.cmd" , |
1539 | dirlen, object, base); |
1540 | if (ret >= sizeof(cmd_file)) { |
1541 | error("%s: too long path was truncated\n" , cmd_file); |
1542 | return; |
1543 | } |
1544 | |
1545 | buf = read_text_file(filename: cmd_file); |
1546 | p = buf; |
1547 | |
1548 | while ((p = strstr(haystack: p, needle: "\n#SYMVER " ))) { |
1549 | char *name; |
1550 | size_t namelen; |
1551 | unsigned int crc; |
1552 | struct symbol *sym; |
1553 | |
1554 | name = p + strlen(s: "\n#SYMVER " ); |
1555 | |
1556 | p = strchr(s: name, c: ' '); |
1557 | if (!p) |
1558 | break; |
1559 | |
1560 | namelen = p - name; |
1561 | p++; |
1562 | |
1563 | if (!isdigit(*p)) |
1564 | continue; /* skip this line */ |
1565 | |
1566 | crc = strtoul(nptr: p, endptr: &p, base: 0); |
1567 | if (*p != '\n') |
1568 | continue; /* skip this line */ |
1569 | |
1570 | name[namelen] = '\0'; |
1571 | |
1572 | /* |
1573 | * sym_find_with_module() may return NULL here. |
1574 | * It typically occurs when CONFIG_TRIM_UNUSED_KSYMS=y. |
1575 | * Since commit e1327a127703, genksyms calculates CRCs of all |
1576 | * symbols, including trimmed ones. Ignore orphan CRCs. |
1577 | */ |
1578 | sym = sym_find_with_module(name, mod); |
1579 | if (sym) |
1580 | sym_set_crc(sym, crc); |
1581 | } |
1582 | |
1583 | free(ptr: buf); |
1584 | } |
1585 | |
1586 | /* |
1587 | * The symbol versions (CRC) are recorded in the .*.cmd files. |
1588 | * Parse them to retrieve CRCs for the current module. |
1589 | */ |
1590 | static void mod_set_crcs(struct module *mod) |
1591 | { |
1592 | char objlist[PATH_MAX]; |
1593 | char *buf, *p, *obj; |
1594 | int ret; |
1595 | |
1596 | if (mod->is_vmlinux) { |
1597 | strcpy(dest: objlist, src: ".vmlinux.objs" ); |
1598 | } else { |
1599 | /* objects for a module are listed in the *.mod file. */ |
1600 | ret = snprintf(s: objlist, maxlen: sizeof(objlist), format: "%s.mod" , mod->name); |
1601 | if (ret >= sizeof(objlist)) { |
1602 | error("%s: too long path was truncated\n" , objlist); |
1603 | return; |
1604 | } |
1605 | } |
1606 | |
1607 | buf = read_text_file(filename: objlist); |
1608 | p = buf; |
1609 | |
1610 | while ((obj = strsep(stringp: &p, delim: "\n" )) && obj[0]) |
1611 | extract_crcs_for_object(object: obj, mod); |
1612 | |
1613 | free(ptr: buf); |
1614 | } |
1615 | |
1616 | static void read_symbols(const char *modname) |
1617 | { |
1618 | const char *symname; |
1619 | char *version; |
1620 | char *license; |
1621 | char *namespace; |
1622 | struct module *mod; |
1623 | struct elf_info info = { }; |
1624 | Elf_Sym *sym; |
1625 | |
1626 | if (!parse_elf(info: &info, filename: modname)) |
1627 | return; |
1628 | |
1629 | if (!strends(str: modname, postfix: ".o" )) { |
1630 | error("%s: filename must be suffixed with .o\n" , modname); |
1631 | return; |
1632 | } |
1633 | |
1634 | /* strip trailing .o */ |
1635 | mod = new_module(name: modname, namelen: strlen(s: modname) - strlen(s: ".o" )); |
1636 | |
1637 | if (!mod->is_vmlinux) { |
1638 | license = get_modinfo(info: &info, tag: "license" ); |
1639 | if (!license) |
1640 | error("missing MODULE_LICENSE() in %s\n" , modname); |
1641 | while (license) { |
1642 | if (!license_is_gpl_compatible(license)) { |
1643 | mod->is_gpl_compatible = false; |
1644 | break; |
1645 | } |
1646 | license = get_next_modinfo(info: &info, tag: "license" , prev: license); |
1647 | } |
1648 | |
1649 | namespace = get_modinfo(info: &info, tag: "import_ns" ); |
1650 | while (namespace) { |
1651 | add_namespace(head: &mod->imported_namespaces, namespace); |
1652 | namespace = get_next_modinfo(info: &info, tag: "import_ns" , |
1653 | prev: namespace); |
1654 | } |
1655 | } |
1656 | |
1657 | if (extra_warn && !get_modinfo(info: &info, tag: "description" )) |
1658 | warn("missing MODULE_DESCRIPTION() in %s\n" , modname); |
1659 | for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { |
1660 | symname = remove_dot(s: info.strtab + sym->st_name); |
1661 | |
1662 | handle_symbol(mod, info: &info, sym, symname); |
1663 | handle_moddevtable(mod, info: &info, sym, symname); |
1664 | } |
1665 | |
1666 | check_sec_ref(mod, elf: &info); |
1667 | |
1668 | if (!mod->is_vmlinux) { |
1669 | version = get_modinfo(info: &info, tag: "version" ); |
1670 | if (version || all_versions) |
1671 | get_src_version(modname: mod->name, sum: mod->srcversion, |
1672 | sumlen: sizeof(mod->srcversion) - 1); |
1673 | } |
1674 | |
1675 | parse_elf_finish(info: &info); |
1676 | |
1677 | if (modversions) { |
1678 | /* |
1679 | * Our trick to get versioning for module struct etc. - it's |
1680 | * never passed as an argument to an exported function, so |
1681 | * the automatic versioning doesn't pick it up, but it's really |
1682 | * important anyhow. |
1683 | */ |
1684 | sym_add_unresolved(name: "module_layout" , mod, false); |
1685 | |
1686 | mod_set_crcs(mod); |
1687 | } |
1688 | } |
1689 | |
1690 | static void read_symbols_from_files(const char *filename) |
1691 | { |
1692 | FILE *in = stdin; |
1693 | char fname[PATH_MAX]; |
1694 | |
1695 | in = fopen(filename: filename, modes: "r" ); |
1696 | if (!in) |
1697 | fatal("Can't open filenames file %s: %m" , filename); |
1698 | |
1699 | while (fgets(s: fname, PATH_MAX, stream: in) != NULL) { |
1700 | if (strends(str: fname, postfix: "\n" )) |
1701 | fname[strlen(s: fname)-1] = '\0'; |
1702 | read_symbols(modname: fname); |
1703 | } |
1704 | |
1705 | fclose(stream: in); |
1706 | } |
1707 | |
1708 | #define SZ 500 |
1709 | |
1710 | /* We first write the generated file into memory using the |
1711 | * following helper, then compare to the file on disk and |
1712 | * only update the later if anything changed */ |
1713 | |
1714 | void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, |
1715 | const char *fmt, ...) |
1716 | { |
1717 | char tmp[SZ]; |
1718 | int len; |
1719 | va_list ap; |
1720 | |
1721 | va_start(ap, fmt); |
1722 | len = vsnprintf(s: tmp, SZ, format: fmt, arg: ap); |
1723 | buf_write(buf, s: tmp, len); |
1724 | va_end(ap); |
1725 | } |
1726 | |
1727 | void buf_write(struct buffer *buf, const char *s, int len) |
1728 | { |
1729 | if (buf->size - buf->pos < len) { |
1730 | buf->size += len + SZ; |
1731 | buf->p = NOFAIL(realloc(buf->p, buf->size)); |
1732 | } |
1733 | strncpy(dest: buf->p + buf->pos, src: s, n: len); |
1734 | buf->pos += len; |
1735 | } |
1736 | |
1737 | static void check_exports(struct module *mod) |
1738 | { |
1739 | struct symbol *s, *exp; |
1740 | |
1741 | list_for_each_entry(s, &mod->unresolved_symbols, list) { |
1742 | const char *basename; |
1743 | exp = find_symbol(name: s->name); |
1744 | if (!exp) { |
1745 | if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS) |
1746 | modpost_log(loglevel: warn_unresolved ? LOG_WARN : LOG_ERROR, |
1747 | fmt: "\"%s\" [%s.ko] undefined!\n" , |
1748 | s->name, mod->name); |
1749 | continue; |
1750 | } |
1751 | if (exp->module == mod) { |
1752 | error("\"%s\" [%s.ko] was exported without definition\n" , |
1753 | s->name, mod->name); |
1754 | continue; |
1755 | } |
1756 | |
1757 | exp->used = true; |
1758 | s->module = exp->module; |
1759 | s->crc_valid = exp->crc_valid; |
1760 | s->crc = exp->crc; |
1761 | |
1762 | basename = strrchr(s: mod->name, c: '/'); |
1763 | if (basename) |
1764 | basename++; |
1765 | else |
1766 | basename = mod->name; |
1767 | |
1768 | if (!contains_namespace(head: &mod->imported_namespaces, namespace: exp->namespace)) { |
1769 | modpost_log(loglevel: allow_missing_ns_imports ? LOG_WARN : LOG_ERROR, |
1770 | fmt: "module %s uses symbol %s from namespace %s, but does not import it.\n" , |
1771 | basename, exp->name, exp->namespace); |
1772 | add_namespace(head: &mod->missing_namespaces, namespace: exp->namespace); |
1773 | } |
1774 | |
1775 | if (!mod->is_gpl_compatible && exp->is_gpl_only) |
1776 | error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n" , |
1777 | basename, exp->name); |
1778 | } |
1779 | } |
1780 | |
1781 | static void handle_white_list_exports(const char *white_list) |
1782 | { |
1783 | char *buf, *p, *name; |
1784 | |
1785 | buf = read_text_file(filename: white_list); |
1786 | p = buf; |
1787 | |
1788 | while ((name = strsep(stringp: &p, delim: "\n" ))) { |
1789 | struct symbol *sym = find_symbol(name); |
1790 | |
1791 | if (sym) |
1792 | sym->used = true; |
1793 | } |
1794 | |
1795 | free(ptr: buf); |
1796 | } |
1797 | |
1798 | static void check_modname_len(struct module *mod) |
1799 | { |
1800 | const char *mod_name; |
1801 | |
1802 | mod_name = strrchr(s: mod->name, c: '/'); |
1803 | if (mod_name == NULL) |
1804 | mod_name = mod->name; |
1805 | else |
1806 | mod_name++; |
1807 | if (strlen(s: mod_name) >= MODULE_NAME_LEN) |
1808 | error("module name is too long [%s.ko]\n" , mod->name); |
1809 | } |
1810 | |
1811 | /** |
1812 | * Header for the generated file |
1813 | **/ |
1814 | static void (struct buffer *b, struct module *mod) |
1815 | { |
1816 | buf_printf(buf: b, fmt: "#include <linux/module.h>\n" ); |
1817 | /* |
1818 | * Include build-salt.h after module.h in order to |
1819 | * inherit the definitions. |
1820 | */ |
1821 | buf_printf(buf: b, fmt: "#define INCLUDE_VERMAGIC\n" ); |
1822 | buf_printf(buf: b, fmt: "#include <linux/build-salt.h>\n" ); |
1823 | buf_printf(buf: b, fmt: "#include <linux/elfnote-lto.h>\n" ); |
1824 | buf_printf(buf: b, fmt: "#include <linux/export-internal.h>\n" ); |
1825 | buf_printf(buf: b, fmt: "#include <linux/vermagic.h>\n" ); |
1826 | buf_printf(buf: b, fmt: "#include <linux/compiler.h>\n" ); |
1827 | buf_printf(buf: b, fmt: "\n" ); |
1828 | buf_printf(buf: b, fmt: "#ifdef CONFIG_UNWINDER_ORC\n" ); |
1829 | buf_printf(buf: b, fmt: "#include <asm/orc_header.h>\n" ); |
1830 | buf_printf(buf: b, fmt: "ORC_HEADER;\n" ); |
1831 | buf_printf(buf: b, fmt: "#endif\n" ); |
1832 | buf_printf(buf: b, fmt: "\n" ); |
1833 | buf_printf(buf: b, fmt: "BUILD_SALT;\n" ); |
1834 | buf_printf(buf: b, fmt: "BUILD_LTO_INFO;\n" ); |
1835 | buf_printf(buf: b, fmt: "\n" ); |
1836 | buf_printf(buf: b, fmt: "MODULE_INFO(vermagic, VERMAGIC_STRING);\n" ); |
1837 | buf_printf(buf: b, fmt: "MODULE_INFO(name, KBUILD_MODNAME);\n" ); |
1838 | buf_printf(buf: b, fmt: "\n" ); |
1839 | buf_printf(buf: b, fmt: "__visible struct module __this_module\n" ); |
1840 | buf_printf(buf: b, fmt: "__section(\".gnu.linkonce.this_module\") = {\n" ); |
1841 | buf_printf(buf: b, fmt: "\t.name = KBUILD_MODNAME,\n" ); |
1842 | if (mod->has_init) |
1843 | buf_printf(buf: b, fmt: "\t.init = init_module,\n" ); |
1844 | if (mod->has_cleanup) |
1845 | buf_printf(buf: b, fmt: "#ifdef CONFIG_MODULE_UNLOAD\n" |
1846 | "\t.exit = cleanup_module,\n" |
1847 | "#endif\n" ); |
1848 | buf_printf(buf: b, fmt: "\t.arch = MODULE_ARCH_INIT,\n" ); |
1849 | buf_printf(buf: b, fmt: "};\n" ); |
1850 | |
1851 | if (!external_module) |
1852 | buf_printf(buf: b, fmt: "\nMODULE_INFO(intree, \"Y\");\n" ); |
1853 | |
1854 | buf_printf(buf: b, |
1855 | fmt: "\n" |
1856 | "#ifdef CONFIG_MITIGATION_RETPOLINE\n" |
1857 | "MODULE_INFO(retpoline, \"Y\");\n" |
1858 | "#endif\n" ); |
1859 | |
1860 | if (strstarts(mod->name, "drivers/staging" )) |
1861 | buf_printf(buf: b, fmt: "\nMODULE_INFO(staging, \"Y\");\n" ); |
1862 | |
1863 | if (strstarts(mod->name, "tools/testing" )) |
1864 | buf_printf(buf: b, fmt: "\nMODULE_INFO(test, \"Y\");\n" ); |
1865 | } |
1866 | |
1867 | static void add_exported_symbols(struct buffer *buf, struct module *mod) |
1868 | { |
1869 | struct symbol *sym; |
1870 | |
1871 | /* generate struct for exported symbols */ |
1872 | buf_printf(buf, fmt: "\n" ); |
1873 | list_for_each_entry(sym, &mod->exported_symbols, list) { |
1874 | if (trim_unused_exports && !sym->used) |
1875 | continue; |
1876 | |
1877 | buf_printf(buf, fmt: "KSYMTAB_%s(%s, \"%s\", \"%s\");\n" , |
1878 | sym->is_func ? "FUNC" : "DATA" , sym->name, |
1879 | sym->is_gpl_only ? "_gpl" : "" , sym->namespace); |
1880 | } |
1881 | |
1882 | if (!modversions) |
1883 | return; |
1884 | |
1885 | /* record CRCs for exported symbols */ |
1886 | buf_printf(buf, fmt: "\n" ); |
1887 | list_for_each_entry(sym, &mod->exported_symbols, list) { |
1888 | if (trim_unused_exports && !sym->used) |
1889 | continue; |
1890 | |
1891 | if (!sym->crc_valid) |
1892 | warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" |
1893 | "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n" , |
1894 | sym->name, mod->name, mod->is_vmlinux ? "" : ".ko" , |
1895 | sym->name); |
1896 | |
1897 | buf_printf(buf, fmt: "SYMBOL_CRC(%s, 0x%08x, \"%s\");\n" , |
1898 | sym->name, sym->crc, sym->is_gpl_only ? "_gpl" : "" ); |
1899 | } |
1900 | } |
1901 | |
1902 | /** |
1903 | * Record CRCs for unresolved symbols |
1904 | **/ |
1905 | static void add_versions(struct buffer *b, struct module *mod) |
1906 | { |
1907 | struct symbol *s; |
1908 | |
1909 | if (!modversions) |
1910 | return; |
1911 | |
1912 | buf_printf(buf: b, fmt: "\n" ); |
1913 | buf_printf(buf: b, fmt: "static const struct modversion_info ____versions[]\n" ); |
1914 | buf_printf(buf: b, fmt: "__used __section(\"__versions\") = {\n" ); |
1915 | |
1916 | list_for_each_entry(s, &mod->unresolved_symbols, list) { |
1917 | if (!s->module) |
1918 | continue; |
1919 | if (!s->crc_valid) { |
1920 | warn("\"%s\" [%s.ko] has no CRC!\n" , |
1921 | s->name, mod->name); |
1922 | continue; |
1923 | } |
1924 | if (strlen(s: s->name) >= MODULE_NAME_LEN) { |
1925 | error("too long symbol \"%s\" [%s.ko]\n" , |
1926 | s->name, mod->name); |
1927 | break; |
1928 | } |
1929 | buf_printf(buf: b, fmt: "\t{ %#8x, \"%s\" },\n" , |
1930 | s->crc, s->name); |
1931 | } |
1932 | |
1933 | buf_printf(buf: b, fmt: "};\n" ); |
1934 | } |
1935 | |
1936 | static void add_depends(struct buffer *b, struct module *mod) |
1937 | { |
1938 | struct symbol *s; |
1939 | int first = 1; |
1940 | |
1941 | /* Clear ->seen flag of modules that own symbols needed by this. */ |
1942 | list_for_each_entry(s, &mod->unresolved_symbols, list) { |
1943 | if (s->module) |
1944 | s->module->seen = s->module->is_vmlinux; |
1945 | } |
1946 | |
1947 | buf_printf(buf: b, fmt: "\n" ); |
1948 | buf_printf(buf: b, fmt: "MODULE_INFO(depends, \"" ); |
1949 | list_for_each_entry(s, &mod->unresolved_symbols, list) { |
1950 | const char *p; |
1951 | if (!s->module) |
1952 | continue; |
1953 | |
1954 | if (s->module->seen) |
1955 | continue; |
1956 | |
1957 | s->module->seen = true; |
1958 | p = strrchr(s: s->module->name, c: '/'); |
1959 | if (p) |
1960 | p++; |
1961 | else |
1962 | p = s->module->name; |
1963 | buf_printf(buf: b, fmt: "%s%s" , first ? "" : "," , p); |
1964 | first = 0; |
1965 | } |
1966 | buf_printf(buf: b, fmt: "\");\n" ); |
1967 | } |
1968 | |
1969 | static void add_srcversion(struct buffer *b, struct module *mod) |
1970 | { |
1971 | if (mod->srcversion[0]) { |
1972 | buf_printf(buf: b, fmt: "\n" ); |
1973 | buf_printf(buf: b, fmt: "MODULE_INFO(srcversion, \"%s\");\n" , |
1974 | mod->srcversion); |
1975 | } |
1976 | } |
1977 | |
1978 | static void write_buf(struct buffer *b, const char *fname) |
1979 | { |
1980 | FILE *file; |
1981 | |
1982 | if (error_occurred) |
1983 | return; |
1984 | |
1985 | file = fopen(filename: fname, modes: "w" ); |
1986 | if (!file) { |
1987 | perror(s: fname); |
1988 | exit(status: 1); |
1989 | } |
1990 | if (fwrite(ptr: b->p, size: 1, n: b->pos, s: file) != b->pos) { |
1991 | perror(s: fname); |
1992 | exit(status: 1); |
1993 | } |
1994 | if (fclose(stream: file) != 0) { |
1995 | perror(s: fname); |
1996 | exit(status: 1); |
1997 | } |
1998 | } |
1999 | |
2000 | static void write_if_changed(struct buffer *b, const char *fname) |
2001 | { |
2002 | char *tmp; |
2003 | FILE *file; |
2004 | struct stat st; |
2005 | |
2006 | file = fopen(filename: fname, modes: "r" ); |
2007 | if (!file) |
2008 | goto write; |
2009 | |
2010 | if (fstat(fd: fileno(stream: file), buf: &st) < 0) |
2011 | goto close_write; |
2012 | |
2013 | if (st.st_size != b->pos) |
2014 | goto close_write; |
2015 | |
2016 | tmp = NOFAIL(malloc(b->pos)); |
2017 | if (fread(ptr: tmp, size: 1, n: b->pos, stream: file) != b->pos) |
2018 | goto free_write; |
2019 | |
2020 | if (memcmp(s1: tmp, s2: b->p, n: b->pos) != 0) |
2021 | goto free_write; |
2022 | |
2023 | free(ptr: tmp); |
2024 | fclose(stream: file); |
2025 | return; |
2026 | |
2027 | free_write: |
2028 | free(ptr: tmp); |
2029 | close_write: |
2030 | fclose(stream: file); |
2031 | write: |
2032 | write_buf(b, fname); |
2033 | } |
2034 | |
2035 | static void write_vmlinux_export_c_file(struct module *mod) |
2036 | { |
2037 | struct buffer buf = { }; |
2038 | |
2039 | buf_printf(buf: &buf, |
2040 | fmt: "#include <linux/export-internal.h>\n" ); |
2041 | |
2042 | add_exported_symbols(buf: &buf, mod); |
2043 | write_if_changed(b: &buf, fname: ".vmlinux.export.c" ); |
2044 | free(ptr: buf.p); |
2045 | } |
2046 | |
2047 | /* do sanity checks, and generate *.mod.c file */ |
2048 | static void write_mod_c_file(struct module *mod) |
2049 | { |
2050 | struct buffer buf = { }; |
2051 | char fname[PATH_MAX]; |
2052 | int ret; |
2053 | |
2054 | add_header(b: &buf, mod); |
2055 | add_exported_symbols(buf: &buf, mod); |
2056 | add_versions(b: &buf, mod); |
2057 | add_depends(b: &buf, mod); |
2058 | add_moddevtable(buf: &buf, mod); |
2059 | add_srcversion(b: &buf, mod); |
2060 | |
2061 | ret = snprintf(s: fname, maxlen: sizeof(fname), format: "%s.mod.c" , mod->name); |
2062 | if (ret >= sizeof(fname)) { |
2063 | error("%s: too long path was truncated\n" , fname); |
2064 | goto free; |
2065 | } |
2066 | |
2067 | write_if_changed(b: &buf, fname); |
2068 | |
2069 | free: |
2070 | free(ptr: buf.p); |
2071 | } |
2072 | |
2073 | /* parse Module.symvers file. line format: |
2074 | * 0x12345678<tab>symbol<tab>module<tab>export<tab>namespace |
2075 | **/ |
2076 | static void read_dump(const char *fname) |
2077 | { |
2078 | char *buf, *pos, *line; |
2079 | |
2080 | buf = read_text_file(filename: fname); |
2081 | if (!buf) |
2082 | /* No symbol versions, silently ignore */ |
2083 | return; |
2084 | |
2085 | pos = buf; |
2086 | |
2087 | while ((line = get_line(stringp: &pos))) { |
2088 | char *symname, *namespace, *modname, *d, *export; |
2089 | unsigned int crc; |
2090 | struct module *mod; |
2091 | struct symbol *s; |
2092 | bool gpl_only; |
2093 | |
2094 | if (!(symname = strchr(s: line, c: '\t'))) |
2095 | goto fail; |
2096 | *symname++ = '\0'; |
2097 | if (!(modname = strchr(s: symname, c: '\t'))) |
2098 | goto fail; |
2099 | *modname++ = '\0'; |
2100 | if (!(export = strchr(s: modname, c: '\t'))) |
2101 | goto fail; |
2102 | *export++ = '\0'; |
2103 | if (!(namespace = strchr(s: export, c: '\t'))) |
2104 | goto fail; |
2105 | *namespace++ = '\0'; |
2106 | |
2107 | crc = strtoul(nptr: line, endptr: &d, base: 16); |
2108 | if (*symname == '\0' || *modname == '\0' || *d != '\0') |
2109 | goto fail; |
2110 | |
2111 | if (!strcmp(s1: export, s2: "EXPORT_SYMBOL_GPL" )) { |
2112 | gpl_only = true; |
2113 | } else if (!strcmp(s1: export, s2: "EXPORT_SYMBOL" )) { |
2114 | gpl_only = false; |
2115 | } else { |
2116 | error("%s: unknown license %s. skip" , symname, export); |
2117 | continue; |
2118 | } |
2119 | |
2120 | mod = find_module(modname); |
2121 | if (!mod) { |
2122 | mod = new_module(name: modname, namelen: strlen(s: modname)); |
2123 | mod->from_dump = true; |
2124 | } |
2125 | s = sym_add_exported(name: symname, mod, gpl_only, namespace); |
2126 | sym_set_crc(sym: s, crc); |
2127 | } |
2128 | free(ptr: buf); |
2129 | return; |
2130 | fail: |
2131 | free(ptr: buf); |
2132 | fatal("parse error in symbol dump file\n" ); |
2133 | } |
2134 | |
2135 | static void write_dump(const char *fname) |
2136 | { |
2137 | struct buffer buf = { }; |
2138 | struct module *mod; |
2139 | struct symbol *sym; |
2140 | |
2141 | list_for_each_entry(mod, &modules, list) { |
2142 | if (mod->from_dump) |
2143 | continue; |
2144 | list_for_each_entry(sym, &mod->exported_symbols, list) { |
2145 | if (trim_unused_exports && !sym->used) |
2146 | continue; |
2147 | |
2148 | buf_printf(buf: &buf, fmt: "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n" , |
2149 | sym->crc, sym->name, mod->name, |
2150 | sym->is_gpl_only ? "_GPL" : "" , |
2151 | sym->namespace); |
2152 | } |
2153 | } |
2154 | write_buf(b: &buf, fname); |
2155 | free(ptr: buf.p); |
2156 | } |
2157 | |
2158 | static void write_namespace_deps_files(const char *fname) |
2159 | { |
2160 | struct module *mod; |
2161 | struct namespace_list *ns; |
2162 | struct buffer ns_deps_buf = {}; |
2163 | |
2164 | list_for_each_entry(mod, &modules, list) { |
2165 | |
2166 | if (mod->from_dump || list_empty(head: &mod->missing_namespaces)) |
2167 | continue; |
2168 | |
2169 | buf_printf(buf: &ns_deps_buf, fmt: "%s.ko:" , mod->name); |
2170 | |
2171 | list_for_each_entry(ns, &mod->missing_namespaces, list) |
2172 | buf_printf(buf: &ns_deps_buf, fmt: " %s" , ns->namespace); |
2173 | |
2174 | buf_printf(buf: &ns_deps_buf, fmt: "\n" ); |
2175 | } |
2176 | |
2177 | write_if_changed(b: &ns_deps_buf, fname); |
2178 | free(ptr: ns_deps_buf.p); |
2179 | } |
2180 | |
2181 | struct dump_list { |
2182 | struct list_head list; |
2183 | const char *file; |
2184 | }; |
2185 | |
2186 | int main(int argc, char **argv) |
2187 | { |
2188 | struct module *mod; |
2189 | char *missing_namespace_deps = NULL; |
2190 | char *unused_exports_white_list = NULL; |
2191 | char *dump_write = NULL, *files_source = NULL; |
2192 | int opt; |
2193 | LIST_HEAD(dump_lists); |
2194 | struct dump_list *dl, *dl2; |
2195 | |
2196 | while ((opt = getopt(argc: argc, argv: argv, shortopts: "ei:MmnT:to:au:WwENd:" )) != -1) { |
2197 | switch (opt) { |
2198 | case 'e': |
2199 | external_module = true; |
2200 | break; |
2201 | case 'i': |
2202 | dl = NOFAIL(malloc(sizeof(*dl))); |
2203 | dl->file = optarg; |
2204 | list_add_tail(new: &dl->list, head: &dump_lists); |
2205 | break; |
2206 | case 'M': |
2207 | module_enabled = true; |
2208 | break; |
2209 | case 'm': |
2210 | modversions = true; |
2211 | break; |
2212 | case 'n': |
2213 | ignore_missing_files = true; |
2214 | break; |
2215 | case 'o': |
2216 | dump_write = optarg; |
2217 | break; |
2218 | case 'a': |
2219 | all_versions = true; |
2220 | break; |
2221 | case 'T': |
2222 | files_source = optarg; |
2223 | break; |
2224 | case 't': |
2225 | trim_unused_exports = true; |
2226 | break; |
2227 | case 'u': |
2228 | unused_exports_white_list = optarg; |
2229 | break; |
2230 | case 'W': |
2231 | extra_warn = true; |
2232 | break; |
2233 | case 'w': |
2234 | warn_unresolved = true; |
2235 | break; |
2236 | case 'E': |
2237 | sec_mismatch_warn_only = false; |
2238 | break; |
2239 | case 'N': |
2240 | allow_missing_ns_imports = true; |
2241 | break; |
2242 | case 'd': |
2243 | missing_namespace_deps = optarg; |
2244 | break; |
2245 | default: |
2246 | exit(status: 1); |
2247 | } |
2248 | } |
2249 | |
2250 | list_for_each_entry_safe(dl, dl2, &dump_lists, list) { |
2251 | read_dump(fname: dl->file); |
2252 | list_del(entry: &dl->list); |
2253 | free(ptr: dl); |
2254 | } |
2255 | |
2256 | while (optind < argc) |
2257 | read_symbols(modname: argv[optind++]); |
2258 | |
2259 | if (files_source) |
2260 | read_symbols_from_files(filename: files_source); |
2261 | |
2262 | list_for_each_entry(mod, &modules, list) { |
2263 | if (mod->from_dump || mod->is_vmlinux) |
2264 | continue; |
2265 | |
2266 | check_modname_len(mod); |
2267 | check_exports(mod); |
2268 | } |
2269 | |
2270 | if (unused_exports_white_list) |
2271 | handle_white_list_exports(white_list: unused_exports_white_list); |
2272 | |
2273 | list_for_each_entry(mod, &modules, list) { |
2274 | if (mod->from_dump) |
2275 | continue; |
2276 | |
2277 | if (mod->is_vmlinux) |
2278 | write_vmlinux_export_c_file(mod); |
2279 | else |
2280 | write_mod_c_file(mod); |
2281 | } |
2282 | |
2283 | if (missing_namespace_deps) |
2284 | write_namespace_deps_files(fname: missing_namespace_deps); |
2285 | |
2286 | if (dump_write) |
2287 | write_dump(fname: dump_write); |
2288 | if (sec_mismatch_count && !sec_mismatch_warn_only) |
2289 | error("Section mismatches detected.\n" |
2290 | "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n" ); |
2291 | |
2292 | if (nr_unresolved > MAX_UNRESOLVED_REPORTS) |
2293 | warn("suppressed %u unresolved symbol warnings because there were too many)\n" , |
2294 | nr_unresolved - MAX_UNRESOLVED_REPORTS); |
2295 | |
2296 | return error_occurred ? 1 : 0; |
2297 | } |
2298 | |