blob: 1209e1786af7c033bf7d1aeb9127c6401889d95f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* Postprocess module symbol versions
2 *
3 * Copyright 2003 Kai Germaschewski
4 * Copyright 2002-2004 Rusty Russell, IBM Corporation
Sam Ravnborgdf578e72008-01-11 19:17:15 +01005 * Copyright 2006-2008 Sam Ravnborg
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * 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
Mathieu Desnoyersb2e3e652008-02-13 15:03:39 -080014#define _GNU_SOURCE
Masahiro Yamada5370d4a2020-01-05 00:36:51 +090015#include <elf.h>
Mathieu Desnoyersb2e3e652008-02-13 15:03:39 -080016#include <stdio.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <ctype.h>
Andrew Morton5003bab2010-08-11 00:42:26 -070018#include <string.h>
Rusty Russell712f9b42013-04-04 17:37:38 +103019#include <limits.h>
Guenter Roeckeed380f2013-09-23 15:23:54 +093020#include <errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include "modpost.h"
Sam Ravnborgb817f6f2006-06-09 21:53:55 +020022#include "../../include/linux/license.h"
Alan Jenkins9e1b9b82009-11-07 21:03:54 +000023
Linus Torvalds1da177e2005-04-16 15:20:36 -070024/* Are we using CONFIG_MODVERSIONS? */
Mathias Krause7a3ee752014-08-27 20:28:53 +093025static int modversions = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070026/* Is CONFIG_MODULE_SRCVERSION_ALL set? */
27static int all_versions = 0;
Sam Ravnborg040fcc82006-01-28 22:15:55 +010028/* If we are modposting external module set to 1 */
29static int external_module = 0;
Kirill Korotaevc53ddac2006-09-07 13:08:54 -070030/* Only warn about unresolved symbols */
31static int warn_unresolved = 0;
Ram Paibd5cbce2006-06-08 22:12:53 -070032/* How a symbol is exported */
Sam Ravnborg588ccd72008-01-24 21:12:37 +010033static int sec_mismatch_count = 0;
Masahiro Yamadac7299d92020-12-01 19:34:18 +090034static int sec_mismatch_warn_only = true;
Guenter Roeckeed380f2013-09-23 15:23:54 +093035/* ignore missing files */
36static int ignore_missing_files;
Jessica Yu54b77842020-03-06 17:02:06 +010037/* If set to 1, only warn (instead of error) about missing ns imports */
38static int allow_missing_ns_imports;
Sam Ravnborg588ccd72008-01-24 21:12:37 +010039
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +090040static bool error_occurred;
41
Masahiro Yamada4475dff2021-03-26 03:54:11 +090042/*
43 * Cut off the warnings when there are too many. This typically occurs when
44 * vmlinux is missing. ('make modules' without building vmlinux.)
45 */
46#define MAX_UNRESOLVED_REPORTS 10
47static unsigned int nr_unresolved;
48
Sam Ravnborgc96fca22006-07-01 11:44:23 +020049enum export {
Christoph Hellwig36794822021-02-02 13:13:34 +010050 export_plain,
51 export_gpl,
52 export_unknown
Sam Ravnborgc96fca22006-07-01 11:44:23 +020053};
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Wanlong Gao4fd3e4e2017-06-30 22:07:03 +080055/* In kernel, this size is defined in linux/module.h;
56 * here we use Elf_Addr instead of long for covering cross-compile
57 */
58
59#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
60
Jessica Yu93c95e52020-03-06 17:02:05 +010061void __attribute__((format(printf, 2, 3)))
62modpost_log(enum loglevel loglevel, const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063{
64 va_list arglist;
65
Jessica Yu93c95e52020-03-06 17:02:05 +010066 switch (loglevel) {
67 case LOG_WARN:
68 fprintf(stderr, "WARNING: ");
69 break;
70 case LOG_ERROR:
71 fprintf(stderr, "ERROR: ");
72 break;
73 case LOG_FATAL:
74 fprintf(stderr, "FATAL: ");
75 break;
76 default: /* invalid loglevel, ignore */
77 break;
78 }
79
80 fprintf(stderr, "modpost: ");
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
82 va_start(arglist, fmt);
83 vfprintf(stderr, fmt, arglist);
84 va_end(arglist);
85
Jessica Yu93c95e52020-03-06 17:02:05 +010086 if (loglevel == LOG_FATAL)
87 exit(1);
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +090088 if (loglevel == LOG_ERROR)
89 error_occurred = true;
Matthew Wilcox2a116652006-10-07 05:35:32 -060090}
91
Linus Torvalds1da177e2005-04-16 15:20:36 -070092void *do_nofail(void *ptr, const char *expr)
93{
Sam Ravnborgdf578e72008-01-11 19:17:15 +010094 if (!ptr)
Jessica Yu93c95e52020-03-06 17:02:05 +010095 fatal("Memory allocation failure: %s.\n", expr);
Sam Ravnborgdf578e72008-01-11 19:17:15 +010096
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 return ptr;
98}
99
Masahiro Yamadaac5100f2020-06-01 14:57:17 +0900100char *read_text_file(const char *filename)
101{
102 struct stat st;
103 size_t nbytes;
104 int fd;
105 char *buf;
106
107 fd = open(filename, O_RDONLY);
108 if (fd < 0) {
109 perror(filename);
110 exit(1);
111 }
112
113 if (fstat(fd, &st) < 0) {
114 perror(filename);
115 exit(1);
116 }
117
118 buf = NOFAIL(malloc(st.st_size + 1));
119
120 nbytes = st.st_size;
121
122 while (nbytes) {
123 ssize_t bytes_read;
124
125 bytes_read = read(fd, buf, nbytes);
126 if (bytes_read < 0) {
127 perror(filename);
128 exit(1);
129 }
130
131 nbytes -= bytes_read;
132 }
133 buf[st.st_size] = '\0';
134
135 close(fd);
136
137 return buf;
138}
139
140char *get_line(char **stringp)
141{
H. Nikolaus Schaller736bb112020-07-01 08:18:27 +0200142 char *orig = *stringp, *next;
143
Masahiro Yamadaac5100f2020-06-01 14:57:17 +0900144 /* do not return the unwanted extra line at EOF */
H. Nikolaus Schaller736bb112020-07-01 08:18:27 +0200145 if (!orig || *orig == '\0')
Masahiro Yamadaac5100f2020-06-01 14:57:17 +0900146 return NULL;
147
Wolfram Sang6020db52020-07-26 23:44:19 +0200148 /* don't use strsep here, it is not available everywhere */
H. Nikolaus Schaller736bb112020-07-01 08:18:27 +0200149 next = strchr(orig, '\n');
150 if (next)
151 *next++ = '\0';
152
153 *stringp = next;
154
155 return orig;
Masahiro Yamadaac5100f2020-06-01 14:57:17 +0900156}
157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158/* A list of all modules we processed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159static struct module *modules;
160
Masahiro Yamada8b185742018-05-09 18:50:40 +0900161static struct module *find_module(const char *modname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162{
163 struct module *mod;
164
165 for (mod = modules; mod; mod = mod->next)
166 if (strcmp(mod->name, modname) == 0)
167 break;
168 return mod;
169}
170
Rusty Russelld4ef1c32013-04-04 17:37:32 +1030171static struct module *new_module(const char *modname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
173 struct module *mod;
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100174
Masahiro Yamadaa82f7942020-06-01 14:57:29 +0900175 mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 memset(mod, 0, sizeof(*mod));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
178 /* add to list */
Masahiro Yamadaa82f7942020-06-01 14:57:29 +0900179 strcpy(mod->name, modname);
Masahiro Yamada4de7b622020-06-01 14:57:30 +0900180 mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0);
Sam Ravnborgb817f6f2006-06-09 21:53:55 +0200181 mod->gpl_compatible = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 mod->next = modules;
183 modules = mod;
184
185 return mod;
186}
187
188/* A hash of all exported symbols,
189 * struct symbol is also used for lists of unresolved symbols */
190
191#define SYMBOL_HASH_SIZE 1024
192
193struct symbol {
194 struct symbol *next;
195 struct module *module;
196 unsigned int crc;
197 int crc_valid;
Masahiro Yamada389eb3f2019-10-03 16:58:22 +0900198 char *namespace;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 unsigned int weak:1;
Denis Efremov15bfc232019-08-01 09:06:57 +0300200 unsigned int is_static:1; /* 1 if symbol is not global */
Ram Paibd5cbce2006-06-08 22:12:53 -0700201 enum export export; /* Type of export */
Gustavo A. R. Silva859c8172020-05-07 13:56:01 -0500202 char name[];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203};
204
205static struct symbol *symbolhash[SYMBOL_HASH_SIZE];
206
Bhaskar Chowdhuryf3945832021-03-26 11:22:19 +0530207/* This is based on the hash algorithm from gdbm, via tdb */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208static inline unsigned int tdb_hash(const char *name)
209{
210 unsigned value; /* Used to compute the hash value. */
211 unsigned i; /* Used to cycle through random values. */
212
213 /* Set the initial value from the key size. */
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100214 for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
216
217 return (1103515243 * value + 12345);
218}
219
Sam Ravnborg5c3ead82006-01-28 17:19:35 +0100220/**
221 * Allocate a new symbols for use in the hash of exported symbols or
222 * the list of unresolved symbols per module
223 **/
224static struct symbol *alloc_symbol(const char *name, unsigned int weak,
225 struct symbol *next)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226{
227 struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
228
229 memset(s, 0, sizeof(*s));
230 strcpy(s->name, name);
231 s->weak = weak;
232 s->next = next;
Denis Efremov15bfc232019-08-01 09:06:57 +0300233 s->is_static = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 return s;
235}
236
237/* For the hash of exported symbols */
Ram Paibd5cbce2006-06-08 22:12:53 -0700238static struct symbol *new_symbol(const char *name, struct module *module,
239 enum export export)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
241 unsigned int hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
243 hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
Masahiro Yamada7ef9ab32019-11-15 02:42:26 +0900244 symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
245
246 return symbolhash[hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247}
248
Sam Ravnborg5c3ead82006-01-28 17:19:35 +0100249static struct symbol *find_symbol(const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250{
251 struct symbol *s;
252
253 /* For our purposes, .foo matches foo. PPC64 needs this. */
254 if (name[0] == '.')
255 name++;
256
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100257 for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 if (strcmp(s->name, name) == 0)
259 return s;
260 }
261 return NULL;
262}
263
Matthias Maennichcb9b55d2019-09-06 11:32:28 +0100264static bool contains_namespace(struct namespace_list *list,
265 const char *namespace)
266{
Masahiro Yamada76b54cf2019-10-29 21:38:09 +0900267 for (; list; list = list->next)
268 if (!strcmp(list->namespace, namespace))
Matthias Maennichcb9b55d2019-09-06 11:32:28 +0100269 return true;
270
271 return false;
272}
273
274static void add_namespace(struct namespace_list **list, const char *namespace)
275{
276 struct namespace_list *ns_entry;
277
278 if (!contains_namespace(*list, namespace)) {
279 ns_entry = NOFAIL(malloc(sizeof(struct namespace_list) +
280 strlen(namespace) + 1));
281 strcpy(ns_entry->namespace, namespace);
282 ns_entry->next = *list;
283 *list = ns_entry;
284 }
285}
286
287static bool module_imports_namespace(struct module *module,
288 const char *namespace)
289{
290 return contains_namespace(module->imported_namespaces, namespace);
291}
292
Mathias Krause7a3ee752014-08-27 20:28:53 +0930293static const struct {
Ram Paibd5cbce2006-06-08 22:12:53 -0700294 const char *str;
295 enum export export;
296} export_list[] = {
297 { .str = "EXPORT_SYMBOL", .export = export_plain },
298 { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
Ram Paibd5cbce2006-06-08 22:12:53 -0700299 { .str = "(unknown)", .export = export_unknown },
300};
301
302
303static const char *export_str(enum export ex)
304{
305 return export_list[ex].str;
306}
307
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100308static enum export export_no(const char *s)
Ram Paibd5cbce2006-06-08 22:12:53 -0700309{
310 int i;
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100311
Sam Ravnborg534b89a2006-07-01 10:10:19 +0200312 if (!s)
313 return export_unknown;
Ram Paibd5cbce2006-06-08 22:12:53 -0700314 for (i = 0; export_list[i].export != export_unknown; i++) {
315 if (strcmp(export_list[i].str, s) == 0)
316 return export_list[i].export;
317 }
318 return export_unknown;
319}
320
Masahiro Yamadad2e4d052020-05-25 14:47:04 +0900321static void *sym_get_data_by_offset(const struct elf_info *info,
322 unsigned int secindex, unsigned long offset)
Masahiro Yamada6124c042017-09-06 16:19:05 -0700323{
Xiao Yang4b8a5cf2020-03-18 18:34:16 +0800324 Elf_Shdr *sechdr = &info->sechdrs[secindex];
Masahiro Yamadaafa04592019-11-15 02:42:21 +0900325
Masahiro Yamadaafa04592019-11-15 02:42:21 +0900326 if (info->hdr->e_type != ET_REL)
327 offset -= sechdr->sh_addr;
328
329 return (void *)info->hdr + sechdr->sh_offset + offset;
330}
331
Masahiro Yamadad2e4d052020-05-25 14:47:04 +0900332static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym)
333{
334 return sym_get_data_by_offset(info, get_secindex(info, sym),
335 sym->st_value);
336}
337
Masahiro Yamada565587d2020-05-25 14:47:05 +0900338static const char *sech_name(const struct elf_info *info, Elf_Shdr *sechdr)
339{
340 return sym_get_data_by_offset(info, info->secindex_strings,
341 sechdr->sh_name);
342}
343
344static const char *sec_name(const struct elf_info *info, int secindex)
345{
346 return sech_name(info, &info->sechdrs[secindex]);
347}
348
Alessio Igor Bogani62a26352011-07-14 08:51:16 +0200349#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
350
351static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
352{
353 const char *secname = sec_name(elf, sec);
354
355 if (strstarts(secname, "___ksymtab+"))
356 return export_plain;
Alessio Igor Bogani62a26352011-07-14 08:51:16 +0200357 else if (strstarts(secname, "___ksymtab_gpl+"))
358 return export_gpl;
Alessio Igor Bogani62a26352011-07-14 08:51:16 +0200359 else
360 return export_unknown;
361}
362
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200363static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
Ram Paibd5cbce2006-06-08 22:12:53 -0700364{
365 if (sec == elf->export_sec)
366 return export_plain;
367 else if (sec == elf->export_gpl_sec)
368 return export_gpl;
Ram Paibd5cbce2006-06-08 22:12:53 -0700369 else
370 return export_unknown;
371}
372
Masahiro Yamadae84f9fb2019-11-15 02:42:22 +0900373static const char *namespace_from_kstrtabns(const struct elf_info *info,
374 const Elf_Sym *sym)
Matthias Maennichcb9b55d2019-09-06 11:32:28 +0100375{
Masahiro Yamadae84f9fb2019-11-15 02:42:22 +0900376 const char *value = sym_get_data(info, sym);
Matthias Maennich69923202019-10-18 10:31:42 +0100377 return value[0] ? value : NULL;
Matthias Maennichcb9b55d2019-09-06 11:32:28 +0100378}
379
Matthias Maennicha2b11182019-10-18 10:31:40 +0100380static void sym_update_namespace(const char *symname, const char *namespace)
381{
382 struct symbol *s = find_symbol(symname);
383
384 /*
385 * That symbol should have been created earlier and thus this is
386 * actually an assertion.
387 */
388 if (!s) {
Masahiro Yamadabc72d722020-12-01 19:34:14 +0900389 error("Could not update namespace(%s) for symbol %s\n",
390 namespace, symname);
Matthias Maennicha2b11182019-10-18 10:31:40 +0100391 return;
392 }
393
394 free(s->namespace);
395 s->namespace =
396 namespace && namespace[0] ? NOFAIL(strdup(namespace)) : NULL;
397}
398
Sam Ravnborg5c3ead82006-01-28 17:19:35 +0100399/**
400 * Add an exported symbol - it may have already been added without a
401 * CRC, in this case just update the CRC
402 **/
Matthias Maennich9ae5bd12019-10-18 10:31:41 +0100403static struct symbol *sym_add_exported(const char *name, struct module *mod,
404 enum export export)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
406 struct symbol *s = find_symbol(name);
407
408 if (!s) {
Ram Paibd5cbce2006-06-08 22:12:53 -0700409 s = new_symbol(name, mod, export);
Masahiro Yamada5a438af2020-06-01 14:57:26 +0900410 } else if (!external_module || s->module->is_vmlinux ||
Masahiro Yamada7ef9ab32019-11-15 02:42:26 +0900411 s->module == mod) {
412 warn("%s: '%s' exported twice. Previous export was in %s%s\n",
413 mod->name, name, s->module->name,
Masahiro Yamada5a438af2020-06-01 14:57:26 +0900414 s->module->is_vmlinux ? "" : ".ko");
Masahiro Yamada7ef9ab32019-11-15 02:42:26 +0900415 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 }
Masahiro Yamada7ef9ab32019-11-15 02:42:26 +0900417
418 s->module = mod;
Ram Paibd5cbce2006-06-08 22:12:53 -0700419 s->export = export;
Sam Ravnborg040fcc82006-01-28 22:15:55 +0100420 return s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421}
422
Masahiro Yamada17436942019-11-15 02:42:24 +0900423static void sym_set_crc(const char *name, unsigned int crc)
Sam Ravnborg040fcc82006-01-28 22:15:55 +0100424{
425 struct symbol *s = find_symbol(name);
426
Masahiro Yamada17436942019-11-15 02:42:24 +0900427 /*
428 * Ignore stand-alone __crc_*, which might be auto-generated symbols
429 * such as __*_veneer in ARM ELF.
430 */
431 if (!s)
432 return;
433
Sam Ravnborg040fcc82006-01-28 22:15:55 +0100434 s->crc = crc;
435 s->crc_valid = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
Masahiro Yamada3b09efc2020-06-01 14:57:31 +0900438static void *grab_file(const char *filename, size_t *size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 struct stat st;
Jesper Juhleb3d5cc2012-05-23 22:28:49 +0930441 void *map = MAP_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 int fd;
443
444 fd = open(filename, O_RDONLY);
Jesper Juhleb3d5cc2012-05-23 22:28:49 +0930445 if (fd < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 return NULL;
Jesper Juhleb3d5cc2012-05-23 22:28:49 +0930447 if (fstat(fd, &st))
448 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
450 *size = st.st_size;
451 map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Jesper Juhleb3d5cc2012-05-23 22:28:49 +0930453failed:
454 close(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 if (map == MAP_FAILED)
456 return NULL;
457 return map;
458}
459
Masahiro Yamada3b09efc2020-06-01 14:57:31 +0900460static void release_file(void *file, size_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 munmap(file, size);
463}
464
Sam Ravnborg85bd2fd2007-02-26 15:33:52 +0100465static int parse_elf(struct elf_info *info, const char *filename)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 unsigned int i;
Sam Ravnborg85bd2fd2007-02-26 15:33:52 +0100468 Elf_Ehdr *hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 Elf_Shdr *sechdrs;
470 Elf_Sym *sym;
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200471 const char *secstrings;
472 unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
474 hdr = grab_file(filename, &info->size);
475 if (!hdr) {
Guenter Roeckeed380f2013-09-23 15:23:54 +0930476 if (ignore_missing_files) {
477 fprintf(stderr, "%s: %s (ignored)\n", filename,
478 strerror(errno));
479 return 0;
480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 perror(filename);
Sam Ravnborg6803dc02006-06-24 23:46:54 +0200482 exit(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
484 info->hdr = hdr;
Sam Ravnborg85bd2fd2007-02-26 15:33:52 +0100485 if (info->size < sizeof(*hdr)) {
486 /* file too small, assume this is an empty .o file */
487 return 0;
488 }
489 /* Is this a valid ELF file? */
490 if ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||
491 (hdr->e_ident[EI_MAG1] != ELFMAG1) ||
492 (hdr->e_ident[EI_MAG2] != ELFMAG2) ||
493 (hdr->e_ident[EI_MAG3] != ELFMAG3)) {
494 /* Not an ELF file - silently ignore it */
495 return 0;
496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 /* Fix endianness in ELF header */
Anders Kaseorg7d875a02009-05-03 22:02:55 +0200498 hdr->e_type = TO_NATIVE(hdr->e_type);
499 hdr->e_machine = TO_NATIVE(hdr->e_machine);
500 hdr->e_version = TO_NATIVE(hdr->e_version);
501 hdr->e_entry = TO_NATIVE(hdr->e_entry);
502 hdr->e_phoff = TO_NATIVE(hdr->e_phoff);
503 hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
504 hdr->e_flags = TO_NATIVE(hdr->e_flags);
505 hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize);
506 hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize);
507 hdr->e_phnum = TO_NATIVE(hdr->e_phnum);
508 hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize);
509 hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
510 hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 sechdrs = (void *)hdr + hdr->e_shoff;
512 info->sechdrs = sechdrs;
513
Petr Stetiara83710e2007-08-27 12:15:07 +0200514 /* Check if file offset is correct */
515 if (hdr->e_shoff > info->size) {
Masahiro Yamada3b09efc2020-06-01 14:57:31 +0900516 fatal("section header offset=%lu in file '%s' is bigger than filesize=%zu\n",
517 (unsigned long)hdr->e_shoff, filename, info->size);
Petr Stetiara83710e2007-08-27 12:15:07 +0200518 return 0;
519 }
520
Anders Kaseorg68457562011-05-19 16:55:27 -0600521 if (hdr->e_shnum == SHN_UNDEF) {
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200522 /*
523 * There are more than 64k sections,
524 * read count from .sh_size.
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200525 */
526 info->num_sections = TO_NATIVE(sechdrs[0].sh_size);
527 }
528 else {
529 info->num_sections = hdr->e_shnum;
530 }
531 if (hdr->e_shstrndx == SHN_XINDEX) {
Anders Kaseorg68457562011-05-19 16:55:27 -0600532 info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link);
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200533 }
534 else {
535 info->secindex_strings = hdr->e_shstrndx;
536 }
537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 /* Fix endianness in section headers */
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200539 for (i = 0; i < info->num_sections; i++) {
Anders Kaseorg7d875a02009-05-03 22:02:55 +0200540 sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
541 sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
542 sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
543 sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
544 sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
545 sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
546 sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
547 sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
548 sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign);
549 sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
551 /* Find symbol table. */
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200552 secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
553 for (i = 1; i < info->num_sections; i++) {
Ram Paibd5cbce2006-06-08 22:12:53 -0700554 const char *secname;
Tejun Heo56fc82c2009-02-06 00:48:02 +0900555 int nobits = sechdrs[i].sh_type == SHT_NOBITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Tejun Heo56fc82c2009-02-06 00:48:02 +0900557 if (!nobits && sechdrs[i].sh_offset > info->size) {
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100558 fatal("%s is truncated. sechdrs[i].sh_offset=%lu > "
559 "sizeof(*hrd)=%zu\n", filename,
560 (unsigned long)sechdrs[i].sh_offset,
561 sizeof(*hdr));
Sam Ravnborg85bd2fd2007-02-26 15:33:52 +0100562 return 0;
563 }
Ram Paibd5cbce2006-06-08 22:12:53 -0700564 secname = secstrings + sechdrs[i].sh_name;
565 if (strcmp(secname, ".modinfo") == 0) {
Tejun Heo56fc82c2009-02-06 00:48:02 +0900566 if (nobits)
567 fatal("%s has NOBITS .modinfo\n", filename);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
569 info->modinfo_len = sechdrs[i].sh_size;
Ram Paibd5cbce2006-06-08 22:12:53 -0700570 } else if (strcmp(secname, "__ksymtab") == 0)
571 info->export_sec = i;
572 else if (strcmp(secname, "__ksymtab_gpl") == 0)
573 info->export_gpl_sec = i;
Ram Paibd5cbce2006-06-08 22:12:53 -0700574
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200575 if (sechdrs[i].sh_type == SHT_SYMTAB) {
576 unsigned int sh_link_idx;
577 symtab_idx = i;
578 info->symtab_start = (void *)hdr +
579 sechdrs[i].sh_offset;
580 info->symtab_stop = (void *)hdr +
581 sechdrs[i].sh_offset + sechdrs[i].sh_size;
Anders Kaseorg68457562011-05-19 16:55:27 -0600582 sh_link_idx = sechdrs[i].sh_link;
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200583 info->strtab = (void *)hdr +
584 sechdrs[sh_link_idx].sh_offset;
585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200587 /* 32bit section no. table? ("more than 64k sections") */
588 if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {
589 symtab_shndx_idx = i;
590 info->symtab_shndx_start = (void *)hdr +
591 sechdrs[i].sh_offset;
592 info->symtab_shndx_stop = (void *)hdr +
593 sechdrs[i].sh_offset + sechdrs[i].sh_size;
594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 }
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100596 if (!info->symtab_start)
Sam Ravnborgcb805142006-01-28 16:57:26 +0100597 fatal("%s has no symtab?\n", filename);
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100598
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 /* Fix endianness in symbols */
600 for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
601 sym->st_shndx = TO_NATIVE(sym->st_shndx);
602 sym->st_name = TO_NATIVE(sym->st_name);
603 sym->st_value = TO_NATIVE(sym->st_value);
604 sym->st_size = TO_NATIVE(sym->st_size);
605 }
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200606
607 if (symtab_shndx_idx != ~0U) {
608 Elf32_Word *p;
Anders Kaseorg68457562011-05-19 16:55:27 -0600609 if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link)
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200610 fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n",
Anders Kaseorg68457562011-05-19 16:55:27 -0600611 filename, sechdrs[symtab_shndx_idx].sh_link,
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +0200612 symtab_idx);
613 /* Fix endianness */
614 for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;
615 p++)
616 *p = TO_NATIVE(*p);
617 }
618
Sam Ravnborg85bd2fd2007-02-26 15:33:52 +0100619 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620}
621
Sam Ravnborg5c3ead82006-01-28 17:19:35 +0100622static void parse_elf_finish(struct elf_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 release_file(info->hdr, info->size);
625}
626
Sam Ravnborg4d7365d2008-06-12 15:02:55 +0200627static int ignore_undef_symbol(struct elf_info *info, const char *symname)
628{
629 /* ignore __this_module, it will be resolved shortly */
Masahiro Yamadab2c5cdc2018-05-09 16:23:45 +0900630 if (strcmp(symname, "__this_module") == 0)
Sam Ravnborg4d7365d2008-06-12 15:02:55 +0200631 return 1;
632 /* ignore global offset table */
633 if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
634 return 1;
635 if (info->hdr->e_machine == EM_PPC)
636 /* Special register function linked on all modules during final link of .ko */
Masahiro Yamadad62c4762018-05-09 18:50:38 +0900637 if (strstarts(symname, "_restgpr_") ||
638 strstarts(symname, "_savegpr_") ||
639 strstarts(symname, "_rest32gpr_") ||
640 strstarts(symname, "_save32gpr_") ||
641 strstarts(symname, "_restvr_") ||
642 strstarts(symname, "_savevr_"))
Sam Ravnborg4d7365d2008-06-12 15:02:55 +0200643 return 1;
Stephen Rothwell7fca5dc2010-06-29 20:08:42 +0000644 if (info->hdr->e_machine == EM_PPC64)
645 /* Special register function linked on all modules during final link of .ko */
Masahiro Yamadad62c4762018-05-09 18:50:38 +0900646 if (strstarts(symname, "_restgpr0_") ||
647 strstarts(symname, "_savegpr0_") ||
648 strstarts(symname, "_restvr_") ||
649 strstarts(symname, "_savevr_") ||
Alan Modrac1536932016-01-15 20:52:22 +1100650 strcmp(symname, ".TOC.") == 0)
Stephen Rothwell7fca5dc2010-06-29 20:08:42 +0000651 return 1;
Sam Ravnborg4d7365d2008-06-12 15:02:55 +0200652 /* Do not ignore this symbol */
653 return 0;
654}
655
Masahiro Yamada17436942019-11-15 02:42:24 +0900656static void handle_modversion(const struct module *mod,
657 const struct elf_info *info,
658 const Elf_Sym *sym, const char *symname)
659{
660 unsigned int crc;
661
662 if (sym->st_shndx == SHN_UNDEF) {
Mark Brown4a679592021-06-07 15:02:06 +0100663 warn("EXPORT symbol \"%s\" [%s%s] version ...\n"
664 "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n",
665 symname, mod->name, mod->is_vmlinux ? "" : ".ko",
666 symname);
667
Masahiro Yamada17436942019-11-15 02:42:24 +0900668 return;
669 }
670
671 if (sym->st_shndx == SHN_ABS) {
672 crc = sym->st_value;
673 } else {
674 unsigned int *crcp;
675
676 /* symbol points to the CRC in the ELF object */
677 crcp = sym_get_data(info, sym);
678 crc = TO_NATIVE(*crcp);
679 }
680 sym_set_crc(symname, crc);
681}
682
Masahiro Yamada9bd2a092019-11-15 02:42:23 +0900683static void handle_symbol(struct module *mod, struct elf_info *info,
684 const Elf_Sym *sym, const char *symname)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685{
Alessio Igor Bogani62a26352011-07-14 08:51:16 +0200686 enum export export;
Masahiro Yamada389eb3f2019-10-03 16:58:22 +0900687 const char *name;
Alessio Igor Bogani62a26352011-07-14 08:51:16 +0200688
Masahiro Yamada33795762020-06-01 14:57:24 +0900689 if (strstarts(symname, "__ksymtab"))
Alessio Igor Bogani62a26352011-07-14 08:51:16 +0200690 export = export_from_secname(info, get_secindex(info, sym));
691 else
692 export = export_from_sec(info, get_secindex(info, sym));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694 switch (sym->st_shndx) {
695 case SHN_COMMON:
Masahiro Yamadad62c4762018-05-09 18:50:38 +0900696 if (strstarts(symname, "__gnu_lto_")) {
Andi Kleenef178f92014-02-08 09:01:17 +0100697 /* Should warn here, but modpost runs before the linker */
698 } else
699 warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 case SHN_UNDEF:
702 /* undefined symbol */
703 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
704 ELF_ST_BIND(sym->st_info) != STB_WEAK)
705 break;
Sam Ravnborg4d7365d2008-06-12 15:02:55 +0200706 if (ignore_undef_symbol(info, symname))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 if (info->hdr->e_machine == EM_SPARC ||
709 info->hdr->e_machine == EM_SPARCV9) {
710 /* Ignore register directives. */
Ben Colline8d529012005-08-19 13:44:57 -0700711 if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 break;
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100713 if (symname[0] == '.') {
Randy Dunlap1f3aa902018-08-15 12:30:38 -0700714 char *munged = NOFAIL(strdup(symname));
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100715 munged[0] = '_';
716 munged[1] = toupper(munged[1]);
717 symname = munged;
718 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 }
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100720
Rusty Russellb92021b2013-03-15 15:04:17 +1030721 mod->unres = alloc_symbol(symname,
722 ELF_ST_BIND(sym->st_info) == STB_WEAK,
723 mod->unres);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 break;
725 default:
726 /* All exported symbols */
Masahiro Yamadad62c4762018-05-09 18:50:38 +0900727 if (strstarts(symname, "__ksymtab_")) {
Matthias Maennichcb9b55d2019-09-06 11:32:28 +0100728 name = symname + strlen("__ksymtab_");
Matthias Maennich9ae5bd12019-10-18 10:31:41 +0100729 sym_add_exported(name, mod, export);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 }
Masahiro Yamadab2c5cdc2018-05-09 16:23:45 +0900731 if (strcmp(symname, "init_module") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 mod->has_init = 1;
Masahiro Yamadab2c5cdc2018-05-09 16:23:45 +0900733 if (strcmp(symname, "cleanup_module") == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 mod->has_cleanup = 1;
735 break;
736 }
737}
738
Sam Ravnborg5c3ead82006-01-28 17:19:35 +0100739/**
740 * Parse tag=value strings from .modinfo section
741 **/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742static char *next_string(char *string, unsigned long *secsize)
743{
744 /* Skip non-zero chars */
745 while (string[0]) {
746 string++;
747 if ((*secsize)-- <= 1)
748 return NULL;
749 }
750
751 /* Skip any zero padding. */
752 while (!string[0]) {
753 string++;
754 if ((*secsize)-- <= 1)
755 return NULL;
756 }
757 return string;
758}
759
Masahiro Yamadabca2cce2018-05-09 18:50:37 +0900760static char *get_next_modinfo(struct elf_info *info, const char *tag,
761 char *prev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762{
763 char *p;
764 unsigned int taglen = strlen(tag);
Masahiro Yamadabca2cce2018-05-09 18:50:37 +0900765 char *modinfo = info->modinfo;
766 unsigned long size = info->modinfo_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Masahiro Yamadabca2cce2018-05-09 18:50:37 +0900768 if (prev) {
769 size -= prev - modinfo;
770 modinfo = next_string(prev, &size);
Sam Ravnborgb817f6f2006-06-09 21:53:55 +0200771 }
772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 for (p = modinfo; p; p = next_string(p, &size)) {
774 if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
775 return p + taglen + 1;
776 }
777 return NULL;
778}
779
Masahiro Yamadabca2cce2018-05-09 18:50:37 +0900780static char *get_modinfo(struct elf_info *info, const char *tag)
Sam Ravnborgb817f6f2006-06-09 21:53:55 +0200781
782{
Masahiro Yamadabca2cce2018-05-09 18:50:37 +0900783 return get_next_modinfo(info, tag, NULL);
Sam Ravnborgb817f6f2006-06-09 21:53:55 +0200784}
785
Sam Ravnborg93684d32006-02-19 11:53:35 +0100786/**
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +0100787 * Test if string s ends in string sub
788 * return 0 if match
789 **/
790static int strrcmp(const char *s, const char *sub)
791{
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100792 int slen, sublen;
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100793
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +0100794 if (!s || !sub)
795 return 1;
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100796
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +0100797 slen = strlen(s);
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100798 sublen = strlen(sub);
Sam Ravnborg62070fa2006-03-03 16:46:04 +0100799
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +0100800 if ((slen == 0) || (sublen == 0))
801 return 1;
802
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100803 if (sublen > slen)
804 return 1;
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +0100805
Sam Ravnborgdf578e72008-01-11 19:17:15 +0100806 return memcmp(s + slen - sublen, sub, sublen);
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +0100807}
808
Sam Ravnborgff13f922008-01-23 19:54:27 +0100809static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
810{
Sam Ravnborg58fb0d42008-01-23 21:13:50 +0100811 if (sym)
812 return elf->strtab + sym->st_name;
813 else
Sam Ravnborgf6667512008-02-06 21:51:18 +0100814 return "(unknown)";
Sam Ravnborgff13f922008-01-23 19:54:27 +0100815}
816
Sam Ravnborg10668222008-01-13 22:21:31 +0100817/* The pattern is an array of simple patterns.
818 * "foo" will match an exact string equal to "foo"
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100819 * "*foo" will match a string that ends with "foo"
Sam Ravnborg10668222008-01-13 22:21:31 +0100820 * "foo*" will match a string that begins with "foo"
Paul Gortmaker09c20c02015-04-20 10:20:26 +0930821 * "*foo*" will match a string that contains "foo"
Sam Ravnborg10668222008-01-13 22:21:31 +0100822 */
Trevor Keith5c725132009-09-22 16:43:38 -0700823static int match(const char *sym, const char * const pat[])
Sam Ravnborg10668222008-01-13 22:21:31 +0100824{
825 const char *p;
826 while (*pat) {
827 p = *pat++;
828 const char *endp = p + strlen(p) - 1;
829
Paul Gortmaker09c20c02015-04-20 10:20:26 +0930830 /* "*foo*" */
831 if (*p == '*' && *endp == '*') {
Denis Efremov6f02bdf2019-08-27 15:20:23 +0300832 char *bare = NOFAIL(strndup(p + 1, strlen(p) - 2));
833 char *here = strstr(sym, bare);
Paul Gortmaker09c20c02015-04-20 10:20:26 +0930834
Paul Gortmaker09c20c02015-04-20 10:20:26 +0930835 free(bare);
836 if (here != NULL)
837 return 1;
838 }
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100839 /* "*foo" */
Paul Gortmaker09c20c02015-04-20 10:20:26 +0930840 else if (*p == '*') {
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100841 if (strrcmp(sym, p + 1) == 0)
842 return 1;
843 }
Sam Ravnborg10668222008-01-13 22:21:31 +0100844 /* "foo*" */
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100845 else if (*endp == '*') {
Sam Ravnborg10668222008-01-13 22:21:31 +0100846 if (strncmp(sym, p, strlen(p) - 1) == 0)
847 return 1;
848 }
Sam Ravnborg10668222008-01-13 22:21:31 +0100849 /* no wildcards */
850 else {
851 if (strcmp(p, sym) == 0)
852 return 1;
853 }
854 }
855 /* no match */
856 return 0;
857}
858
Sam Ravnborg10668222008-01-13 22:21:31 +0100859/* sections that we do not want to do full section mismatch check on */
Mathias Krause7a3ee752014-08-27 20:28:53 +0930860static const char *const section_white_list[] =
Sam Ravnborg4391ed62009-05-04 13:05:26 +0200861{
862 ".comment*",
863 ".debug*",
Chen Gang4d10c222013-08-20 15:33:19 +0930864 ".cranges", /* sh64 */
H.J. Lu11215842010-12-15 17:11:22 -0800865 ".zdebug*", /* Compressed debug sections. */
David Howells739d8752018-03-08 09:48:46 +0000866 ".GCC.command.line", /* record-gcc-switches */
Sam Ravnborg4391ed62009-05-04 13:05:26 +0200867 ".mdebug*", /* alpha, score, mips etc. */
868 ".pdr", /* alpha, score, mips etc. */
869 ".stab*",
870 ".note*",
871 ".got*",
872 ".toc*",
Max Filippovaf42e972012-09-17 05:44:38 +0400873 ".xt.prop", /* xtensa */
874 ".xt.lit", /* xtensa */
Vineet Guptaf2e207f2013-01-21 17:18:57 +1030875 ".arcextmap*", /* arc */
876 ".gnu.linkonce.arcext*", /* arc : modules */
Noam Camusd1189c62015-10-26 19:51:46 +1030877 ".cmem*", /* EZchip */
878 ".fmt_slot*", /* EZchip */
Andi Kleenef178f92014-02-08 09:01:17 +0100879 ".gnu.lto*",
Josh Poimboeufe390f9a2017-03-01 12:04:44 -0600880 ".discard.*",
Sam Ravnborg4391ed62009-05-04 13:05:26 +0200881 NULL
882};
Sam Ravnborg10668222008-01-13 22:21:31 +0100883
Sam Ravnborge241a632008-01-28 20:13:13 +0100884/*
Anders Kaseorgb614a692009-04-23 16:49:33 -0400885 * This is used to find sections missing the SHF_ALLOC flag.
Sam Ravnborge241a632008-01-28 20:13:13 +0100886 * The cause of this is often a section specified in assembler
Anders Kaseorgb614a692009-04-23 16:49:33 -0400887 * without "ax" / "aw".
Sam Ravnborge241a632008-01-28 20:13:13 +0100888 */
Anders Kaseorgb614a692009-04-23 16:49:33 -0400889static void check_section(const char *modname, struct elf_info *elf,
Masahiro Yamadabb66fc62014-06-10 19:08:13 +0900890 Elf_Shdr *sechdr)
Sam Ravnborge241a632008-01-28 20:13:13 +0100891{
Anders Kaseorgb614a692009-04-23 16:49:33 -0400892 const char *sec = sech_name(elf, sechdr);
Sam Ravnborge241a632008-01-28 20:13:13 +0100893
Anders Kaseorgb614a692009-04-23 16:49:33 -0400894 if (sechdr->sh_type == SHT_PROGBITS &&
895 !(sechdr->sh_flags & SHF_ALLOC) &&
896 !match(sec, section_white_list)) {
897 warn("%s (%s): unexpected non-allocatable section.\n"
898 "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
899 "Note that for example <linux/init.h> contains\n"
900 "section definitions for use in .S files.\n\n",
901 modname, sec);
Sam Ravnborge241a632008-01-28 20:13:13 +0100902 }
Sam Ravnborge241a632008-01-28 20:13:13 +0100903}
904
905
906
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100907#define ALL_INIT_DATA_SECTIONS \
Rasmus Villemoesa0d8f802014-07-27 07:28:01 +0930908 ".init.setup", ".init.rodata", ".meminit.rodata", \
909 ".init.data", ".meminit.data"
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100910#define ALL_EXIT_DATA_SECTIONS \
Rasmus Villemoesa0d8f802014-07-27 07:28:01 +0930911 ".exit.data", ".memexit.data"
Sam Ravnborg10668222008-01-13 22:21:31 +0100912
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100913#define ALL_INIT_TEXT_SECTIONS \
Rasmus Villemoesa0d8f802014-07-27 07:28:01 +0930914 ".init.text", ".meminit.text"
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100915#define ALL_EXIT_TEXT_SECTIONS \
Rasmus Villemoesa0d8f802014-07-27 07:28:01 +0930916 ".exit.text", ".memexit.text"
Sam Ravnborg10668222008-01-13 22:21:31 +0100917
Sebastian Andrzej Siewiorbb15d8d2012-06-03 20:48:17 +0200918#define ALL_PCI_INIT_SECTIONS \
Rasmus Villemoesa0d8f802014-07-27 07:28:01 +0930919 ".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \
920 ".pci_fixup_enable", ".pci_fixup_resume", \
921 ".pci_fixup_resume_early", ".pci_fixup_suspend"
Sebastian Andrzej Siewiorbb15d8d2012-06-03 20:48:17 +0200922
Paul Gortmakere24f6622013-06-19 19:30:48 -0400923#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS
924#define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS
Uwe Kleine-König4a31a222010-01-29 12:04:26 +0100925
926#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
927#define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
Sam Ravnborg10668222008-01-13 22:21:31 +0100928
Rasmus Villemoesa0d8f802014-07-27 07:28:01 +0930929#define DATA_SECTIONS ".data", ".data.rel"
Quentin Casasnovas157d1972015-04-13 20:42:52 +0930930#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
Thomas Gleixner65538962020-03-09 22:47:17 +0100931 ".kprobes.text", ".cpuidle.text", ".noinstr.text"
Quentin Casasnovas52dc0592015-04-13 20:52:53 +0930932#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
Chris Metcalf673c2c32015-07-08 17:07:41 -0400933 ".fixup", ".entry.text", ".exception.text", ".text.*", \
Christophe Leroy1e688dd22021-04-13 16:38:10 +0000934 ".coldtext", ".softirqentry.text"
Sam Ravnborg10668222008-01-13 22:21:31 +0100935
Jan Beulichfd6c3a82009-03-12 10:58:33 +0000936#define INIT_SECTIONS ".init.*"
Jan Beulichfd6c3a82009-03-12 10:58:33 +0000937#define MEM_INIT_SECTIONS ".meminit.*"
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100938
Jan Beulichfd6c3a82009-03-12 10:58:33 +0000939#define EXIT_SECTIONS ".exit.*"
Jan Beulichfd6c3a82009-03-12 10:58:33 +0000940#define MEM_EXIT_SECTIONS ".memexit.*"
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100941
Quentin Casasnovas52dc0592015-04-13 20:52:53 +0930942#define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \
943 TEXT_SECTIONS, OTHER_TEXT_SECTIONS
944
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100945/* init data sections */
Mathias Krause7a3ee752014-08-27 20:28:53 +0930946static const char *const init_data_sections[] =
947 { ALL_INIT_DATA_SECTIONS, NULL };
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100948
949/* all init sections */
Mathias Krause7a3ee752014-08-27 20:28:53 +0930950static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100951
952/* All init and exit sections (code + data) */
Mathias Krause7a3ee752014-08-27 20:28:53 +0930953static const char *const init_exit_sections[] =
Sam Ravnborgeb8f6892008-01-20 20:07:28 +0100954 {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100955
Paul Gortmaker4a3893d2015-04-20 10:20:40 +0930956/* all text sections */
957static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL };
958
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100959/* data section */
Mathias Krause7a3ee752014-08-27 20:28:53 +0930960static const char *const data_sections[] = { DATA_SECTIONS, NULL };
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100961
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100962
963/* symbols in .data that may refer to init/exit sections */
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +0100964#define DEFAULT_SYMBOL_WHITE_LIST \
965 "*driver", \
966 "*_template", /* scsi uses *_template a lot */ \
967 "*_timer", /* arm uses ops structures named _timer a lot */ \
968 "*_sht", /* scsi also used *_sht to some extent */ \
969 "*_ops", \
970 "*_probe", \
971 "*_probe_one", \
972 "*_console"
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100973
Mathias Krause7a3ee752014-08-27 20:28:53 +0930974static const char *const head_sections[] = { ".head.text*", NULL };
975static const char *const linker_symbols[] =
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100976 { "__init_begin", "_sinittext", "_einittext", NULL };
Paul Gortmaker4a3893d2015-04-20 10:20:40 +0930977static const char *const optim_symbols[] = { "*.constprop.*", NULL };
Sam Ravnborg6c5bd232008-01-20 10:43:27 +0100978
Sam Ravnborg588ccd72008-01-24 21:12:37 +0100979enum mismatch {
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +0100980 TEXT_TO_ANY_INIT,
981 DATA_TO_ANY_INIT,
982 TEXT_TO_ANY_EXIT,
983 DATA_TO_ANY_EXIT,
984 XXXINIT_TO_SOME_INIT,
985 XXXEXIT_TO_SOME_EXIT,
986 ANY_INIT_TO_ANY_EXIT,
987 ANY_EXIT_TO_ANY_INIT,
Sam Ravnborg588ccd72008-01-24 21:12:37 +0100988 EXPORT_TO_INIT_EXIT,
Quentin Casasnovas52dc0592015-04-13 20:52:53 +0930989 EXTABLE_TO_NON_TEXT,
Sam Ravnborg588ccd72008-01-24 21:12:37 +0100990};
991
Quentin Casasnovase5d8f592015-04-13 20:55:15 +0930992/**
Bhaskar Chowdhuryf3945832021-03-26 11:22:19 +0530993 * Describe how to match sections on different criteria:
Quentin Casasnovase5d8f592015-04-13 20:55:15 +0930994 *
995 * @fromsec: Array of sections to be matched.
996 *
997 * @bad_tosec: Relocations applied to a section in @fromsec to a section in
998 * this array is forbidden (black-list). Can be empty.
999 *
1000 * @good_tosec: Relocations applied to a section in @fromsec must be
Bhaskar Chowdhuryf3945832021-03-26 11:22:19 +05301001 * targeting sections in this array (white-list). Can be empty.
Quentin Casasnovase5d8f592015-04-13 20:55:15 +09301002 *
1003 * @mismatch: Type of mismatch.
1004 *
1005 * @symbol_white_list: Do not match a relocation to a symbol in this list
Bhaskar Chowdhuryf3945832021-03-26 11:22:19 +05301006 * even if it is targeting a section in @bad_to_sec.
Quentin Casasnovase5d8f592015-04-13 20:55:15 +09301007 *
1008 * @handler: Specific handler to call when a match is found. If NULL,
1009 * default_mismatch_handler() will be called.
1010 *
1011 */
Sam Ravnborg10668222008-01-13 22:21:31 +01001012struct sectioncheck {
1013 const char *fromsec[20];
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301014 const char *bad_tosec[20];
1015 const char *good_tosec[20];
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001016 enum mismatch mismatch;
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001017 const char *symbol_white_list[20];
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301018 void (*handler)(const char *modname, struct elf_info *elf,
1019 const struct sectioncheck* const mismatch,
1020 Elf_Rela *r, Elf_Sym *sym, const char *fromsec);
1021
Sam Ravnborg10668222008-01-13 22:21:31 +01001022};
1023
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301024static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
1025 const struct sectioncheck* const mismatch,
1026 Elf_Rela *r, Elf_Sym *sym,
1027 const char *fromsec);
1028
Mathias Krause7a3ee752014-08-27 20:28:53 +09301029static const struct sectioncheck sectioncheck[] = {
Sam Ravnborg10668222008-01-13 22:21:31 +01001030/* Do not reference init/exit code/data from
1031 * normal code and data
1032 */
1033{
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001034 .fromsec = { TEXT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301035 .bad_tosec = { ALL_INIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001036 .mismatch = TEXT_TO_ANY_INIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001037 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001038},
1039{
1040 .fromsec = { DATA_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301041 .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001042 .mismatch = DATA_TO_ANY_INIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001043 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001044},
1045{
Uwe Kleine-König0db252452010-01-30 21:14:23 +01001046 .fromsec = { DATA_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301047 .bad_tosec = { INIT_SECTIONS, NULL },
Uwe Kleine-König0db252452010-01-30 21:14:23 +01001048 .mismatch = DATA_TO_ANY_INIT,
1049 .symbol_white_list = {
1050 "*_template", "*_timer", "*_sht", "*_ops",
1051 "*_probe", "*_probe_one", "*_console", NULL
1052 },
1053},
1054{
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001055 .fromsec = { TEXT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301056 .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001057 .mismatch = TEXT_TO_ANY_EXIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001058 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001059},
1060{
1061 .fromsec = { DATA_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301062 .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001063 .mismatch = DATA_TO_ANY_EXIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001064 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborgeb8f6892008-01-20 20:07:28 +01001065},
Paul Gortmakere24f6622013-06-19 19:30:48 -04001066/* Do not reference init code/data from meminit code/data */
Sam Ravnborgeb8f6892008-01-20 20:07:28 +01001067{
Uwe Kleine-König4a31a222010-01-29 12:04:26 +01001068 .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301069 .bad_tosec = { INIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001070 .mismatch = XXXINIT_TO_SOME_INIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001071 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborgeb8f6892008-01-20 20:07:28 +01001072},
Paul Gortmakere24f6622013-06-19 19:30:48 -04001073/* Do not reference exit code/data from memexit code/data */
Sam Ravnborgeb8f6892008-01-20 20:07:28 +01001074{
Uwe Kleine-König4a31a222010-01-29 12:04:26 +01001075 .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301076 .bad_tosec = { EXIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001077 .mismatch = XXXEXIT_TO_SOME_EXIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001078 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborg10668222008-01-13 22:21:31 +01001079},
1080/* Do not use exit code/data from init code */
1081{
Sam Ravnborgeb8f6892008-01-20 20:07:28 +01001082 .fromsec = { ALL_INIT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301083 .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001084 .mismatch = ANY_INIT_TO_ANY_EXIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001085 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborg10668222008-01-13 22:21:31 +01001086},
1087/* Do not use init code/data from exit code */
1088{
Sam Ravnborgeb8f6892008-01-20 20:07:28 +01001089 .fromsec = { ALL_EXIT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301090 .bad_tosec = { ALL_INIT_SECTIONS, NULL },
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001091 .mismatch = ANY_EXIT_TO_ANY_INIT,
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001092 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Sam Ravnborg10668222008-01-13 22:21:31 +01001093},
Sebastian Andrzej Siewiorbb15d8d2012-06-03 20:48:17 +02001094{
1095 .fromsec = { ALL_PCI_INIT_SECTIONS, NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301096 .bad_tosec = { INIT_SECTIONS, NULL },
Sebastian Andrzej Siewiorbb15d8d2012-06-03 20:48:17 +02001097 .mismatch = ANY_INIT_TO_ANY_EXIT,
1098 .symbol_white_list = { NULL },
1099},
Sam Ravnborg10668222008-01-13 22:21:31 +01001100/* Do not export init/exit functions or data */
1101{
1102 .fromsec = { "__ksymtab*", NULL },
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301103 .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001104 .mismatch = EXPORT_TO_INIT_EXIT,
1105 .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301106},
1107{
1108 .fromsec = { "__ex_table", NULL },
1109 /* If you're adding any new black-listed sections in here, consider
1110 * adding a special 'printer' for them in scripts/check_extable.
1111 */
1112 .bad_tosec = { ".altinstr_replacement", NULL },
1113 .good_tosec = {ALL_TEXT_SECTIONS , NULL},
1114 .mismatch = EXTABLE_TO_NON_TEXT,
1115 .handler = extable_mismatch_handler,
Sam Ravnborg10668222008-01-13 22:21:31 +01001116}
1117};
1118
Uwe Kleine-König0d2a6362010-01-30 16:56:20 +01001119static const struct sectioncheck *section_mismatch(
1120 const char *fromsec, const char *tosec)
Sam Ravnborg10668222008-01-13 22:21:31 +01001121{
1122 int i;
1123 int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
1124 const struct sectioncheck *check = &sectioncheck[0];
1125
Quentin Casasnovasc5c34392015-04-16 13:16:41 +09301126 /*
1127 * The target section could be the SHT_NUL section when we're
1128 * handling relocations to un-resolved symbols, trying to match it
David Howells739d8752018-03-08 09:48:46 +00001129 * doesn't make much sense and causes build failures on parisc
1130 * architectures.
Quentin Casasnovasc5c34392015-04-16 13:16:41 +09301131 */
1132 if (*tosec == '\0')
1133 return NULL;
1134
Sam Ravnborg10668222008-01-13 22:21:31 +01001135 for (i = 0; i < elems; i++) {
Quentin Casasnovas050e57f2015-04-13 20:41:04 +09301136 if (match(fromsec, check->fromsec)) {
1137 if (check->bad_tosec[0] && match(tosec, check->bad_tosec))
1138 return check;
1139 if (check->good_tosec[0] && !match(tosec, check->good_tosec))
1140 return check;
1141 }
Sam Ravnborg10668222008-01-13 22:21:31 +01001142 check++;
1143 }
Uwe Kleine-König0d2a6362010-01-30 16:56:20 +01001144 return NULL;
Sam Ravnborg10668222008-01-13 22:21:31 +01001145}
1146
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001147/**
1148 * Whitelist to allow certain references to pass with no warning.
Sam Ravnborg0e0d3142007-05-17 20:14:48 +02001149 *
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001150 * Pattern 1:
1151 * If a module parameter is declared __initdata and permissions=0
1152 * then this is legal despite the warning generated.
1153 * We cannot see value of permissions here, so just ignore
1154 * this pattern.
1155 * The pattern is identified by:
1156 * tosec = .init.data
Sam Ravnborg9209aed2006-03-05 00:16:26 +01001157 * fromsec = .data*
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001158 * atsym =__param*
Sam Ravnborg62070fa2006-03-03 16:46:04 +01001159 *
Rusty Russell6a841522010-08-11 23:04:16 -06001160 * Pattern 1a:
1161 * module_param_call() ops can refer to __init set function if permissions=0
1162 * The pattern is identified by:
1163 * tosec = .init.text
1164 * fromsec = .data*
1165 * atsym = __param_ops_*
1166 *
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001167 * Pattern 2:
Randy Dunlap72ee59b2006-04-15 11:17:12 -07001168 * Many drivers utilise a *driver container with references to
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001169 * add, remove, probe functions etc.
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001170 * the pattern is identified by:
Sam Ravnborg83cda2b2007-07-25 21:52:31 +02001171 * tosec = init or exit section
1172 * fromsec = data section
Sam Ravnborgdf578e72008-01-11 19:17:15 +01001173 * atsym = *driver, *_template, *_sht, *_ops, *_probe,
1174 * *probe_one, *_console, *_timer
Vivek Goyalee6a8542007-01-11 01:52:44 +01001175 *
1176 * Pattern 3:
Sam Ravnborgc9939712009-04-26 11:17:42 +02001177 * Whitelist all references from .head.text to any init section
Sam Ravnborg9bf8cb92007-02-26 17:49:06 +01001178 *
Sam Ravnborg1d8af552007-06-03 00:41:22 +02001179 * Pattern 4:
Vivek Goyalee6a8542007-01-11 01:52:44 +01001180 * Some symbols belong to init section but still it is ok to reference
1181 * these from non-init sections as these symbols don't have any memory
1182 * allocated for them and symbol address and value are same. So even
1183 * if init section is freed, its ok to reference those symbols.
1184 * For ex. symbols marking the init section boundaries.
1185 * This pattern is identified by
1186 * refsymname = __init_begin, _sinittext, _einittext
Sam Ravnborg9bf8cb92007-02-26 17:49:06 +01001187 *
Paul Gortmaker4a3893d2015-04-20 10:20:40 +09301188 * Pattern 5:
1189 * GCC may optimize static inlines when fed constant arg(s) resulting
1190 * in functions like cpumask_empty() -- generating an associated symbol
1191 * cpumask_empty.constprop.3 that appears in the audit. If the const that
1192 * is passed in comes from __init, like say nmi_ipi_mask, we get a
1193 * meaningless section warning. May need to add isra symbols too...
1194 * This pattern is identified by
1195 * tosec = init section
1196 * fromsec = text section
1197 * refsymname = *.constprop.*
1198 *
Paul Walmsleya4d26f12018-11-21 13:14:13 -08001199 * Pattern 6:
1200 * Hide section mismatch warnings for ELF local symbols. The goal
1201 * is to eliminate false positive modpost warnings caused by
1202 * compiler-generated ELF local symbol names such as ".LANCHOR1".
1203 * Autogenerated symbol names bypass modpost's "Pattern 2"
1204 * whitelisting, which relies on pattern-matching against symbol
1205 * names to work. (One situation where gcc can autogenerate ELF
1206 * local symbols is when "-fsection-anchors" is used.)
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001207 **/
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001208static int secref_whitelist(const struct sectioncheck *mismatch,
1209 const char *fromsec, const char *fromsym,
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001210 const char *tosec, const char *tosym)
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001211{
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001212 /* Check for pattern 1 */
Sam Ravnborg6c5bd232008-01-20 10:43:27 +01001213 if (match(tosec, init_data_sections) &&
1214 match(fromsec, data_sections) &&
Masahiro Yamadad62c4762018-05-09 18:50:38 +09001215 strstarts(fromsym, "__param"))
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001216 return 0;
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001217
Rusty Russell6a841522010-08-11 23:04:16 -06001218 /* Check for pattern 1a */
1219 if (strcmp(tosec, ".init.text") == 0 &&
1220 match(fromsec, data_sections) &&
Masahiro Yamadad62c4762018-05-09 18:50:38 +09001221 strstarts(fromsym, "__param_ops_"))
Rusty Russell6a841522010-08-11 23:04:16 -06001222 return 0;
1223
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001224 /* Check for pattern 2 */
Sam Ravnborg6c5bd232008-01-20 10:43:27 +01001225 if (match(tosec, init_exit_sections) &&
1226 match(fromsec, data_sections) &&
Uwe Kleine-Königaf92a822010-01-30 20:52:50 +01001227 match(fromsym, mismatch->symbol_white_list))
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001228 return 0;
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001229
Sam Ravnborg9bf8cb92007-02-26 17:49:06 +01001230 /* Check for pattern 3 */
Sam Ravnborg6c5bd232008-01-20 10:43:27 +01001231 if (match(fromsec, head_sections) &&
1232 match(tosec, init_sections))
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001233 return 0;
Sam Ravnborg9bf8cb92007-02-26 17:49:06 +01001234
Sam Ravnborg1d8af552007-06-03 00:41:22 +02001235 /* Check for pattern 4 */
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001236 if (match(tosym, linker_symbols))
1237 return 0;
Sam Ravnborg9bf8cb92007-02-26 17:49:06 +01001238
Paul Gortmaker4a3893d2015-04-20 10:20:40 +09301239 /* Check for pattern 5 */
1240 if (match(fromsec, text_sections) &&
1241 match(tosec, init_sections) &&
1242 match(fromsym, optim_symbols))
1243 return 0;
1244
Paul Walmsleya4d26f12018-11-21 13:14:13 -08001245 /* Check for pattern 6 */
1246 if (strstarts(fromsym, ".L"))
1247 return 0;
1248
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001249 return 1;
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001250}
1251
Sami Tolvanen5818c682018-10-23 15:15:35 -07001252static inline int is_arm_mapping_symbol(const char *str)
1253{
1254 return str[0] == '$' && strchr("axtd", str[1])
1255 && (str[2] == '\0' || str[2] == '.');
1256}
1257
1258/*
1259 * If there's no name there, ignore it; likewise, ignore it if it's
1260 * one of the magic symbols emitted used by current ARM tools.
1261 *
1262 * Otherwise if find_symbols_between() returns those symbols, they'll
1263 * fail the whitelist tests and cause lots of false alarms ... fixable
1264 * only by merging __exit and __init sections into __text, bloating
1265 * the kernel (which is especially evil on embedded platforms).
1266 */
1267static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
1268{
1269 const char *name = elf->strtab + sym->st_name;
1270
1271 if (!name || !strlen(name))
1272 return 0;
1273 return !is_arm_mapping_symbol(name);
1274}
1275
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001276/**
Sam Ravnborg93684d32006-02-19 11:53:35 +01001277 * Find symbol based on relocation record info.
1278 * In some cases the symbol supplied is a valid symbol so
1279 * return refsym. If st_name != 0 we assume this is a valid symbol.
1280 * In other cases the symbol needs to be looked up in the symbol table
1281 * based on section and address.
1282 * **/
Sam Ravnborg9ad21c32008-01-18 21:04:34 +01001283static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
Sam Ravnborg93684d32006-02-19 11:53:35 +01001284 Elf_Sym *relsym)
1285{
1286 Elf_Sym *sym;
Sam Ravnborg9ad21c32008-01-18 21:04:34 +01001287 Elf_Sym *near = NULL;
1288 Elf64_Sword distance = 20;
1289 Elf64_Sword d;
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001290 unsigned int relsym_secindex;
Sam Ravnborg93684d32006-02-19 11:53:35 +01001291
1292 if (relsym->st_name != 0)
1293 return relsym;
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001294
1295 relsym_secindex = get_secindex(elf, relsym);
Sam Ravnborg93684d32006-02-19 11:53:35 +01001296 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001297 if (get_secindex(elf, sym) != relsym_secindex)
Sam Ravnborg93684d32006-02-19 11:53:35 +01001298 continue;
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001299 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
1300 continue;
Sami Tolvanen5818c682018-10-23 15:15:35 -07001301 if (!is_valid_name(elf, sym))
1302 continue;
Sam Ravnborg93684d32006-02-19 11:53:35 +01001303 if (sym->st_value == addr)
1304 return sym;
Sam Ravnborg9ad21c32008-01-18 21:04:34 +01001305 /* Find a symbol nearby - addr are maybe negative */
1306 d = sym->st_value - addr;
1307 if (d < 0)
1308 d = addr - sym->st_value;
1309 if (d < distance) {
1310 distance = d;
1311 near = sym;
1312 }
Sam Ravnborg93684d32006-02-19 11:53:35 +01001313 }
Sam Ravnborg9ad21c32008-01-18 21:04:34 +01001314 /* We need a close match */
1315 if (distance < 20)
1316 return near;
1317 else
1318 return NULL;
Sam Ravnborg93684d32006-02-19 11:53:35 +01001319}
1320
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001321/*
Sam Ravnborg43c74d12006-03-05 12:02:46 +01001322 * Find symbols before or equal addr and after addr - in the section sec.
1323 * If we find two symbols with equal offset prefer one with a valid name.
1324 * The ELF format may have a better way to detect what type of symbol
1325 * it is, but this works for now.
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001326 **/
Sam Ravnborg157c23c2008-01-22 21:44:32 +01001327static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
1328 const char *sec)
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001329{
1330 Elf_Sym *sym;
Sam Ravnborg157c23c2008-01-22 21:44:32 +01001331 Elf_Sym *near = NULL;
Sam Ravnborg157c23c2008-01-22 21:44:32 +01001332 Elf_Addr distance = ~0;
Sam Ravnborg62070fa2006-03-03 16:46:04 +01001333
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001334 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1335 const char *symsec;
1336
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001337 if (is_shndx_special(sym->st_shndx))
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001338 continue;
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001339 symsec = sec_name(elf, get_secindex(elf, sym));
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001340 if (strcmp(symsec, sec) != 0)
1341 continue;
David Brownellda68d612007-02-20 13:58:16 -08001342 if (!is_valid_name(elf, sym))
1343 continue;
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001344 if (sym->st_value <= addr) {
Sam Ravnborg157c23c2008-01-22 21:44:32 +01001345 if ((addr - sym->st_value) < distance) {
1346 distance = addr - sym->st_value;
1347 near = sym;
1348 } else if ((addr - sym->st_value) == distance) {
1349 near = sym;
Sam Ravnborg43c74d12006-03-05 12:02:46 +01001350 }
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001351 }
1352 }
Sam Ravnborg157c23c2008-01-22 21:44:32 +01001353 return near;
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001354}
1355
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001356/*
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001357 * Convert a section name to the function/data attribute
1358 * .init.text => __init
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001359 * .memexitconst => __memconst
1360 * etc.
Andy Shevchenkocbcf14a92010-08-17 13:36:40 +03001361 *
1362 * The memory of returned value has been allocated on a heap. The user of this
1363 * method should free it after usage.
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001364*/
1365static char *sec2annotation(const char *s)
1366{
1367 if (match(s, init_exit_sections)) {
Randy Dunlap1f3aa902018-08-15 12:30:38 -07001368 char *p = NOFAIL(malloc(20));
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001369 char *r = p;
1370
1371 *p++ = '_';
1372 *p++ = '_';
1373 if (*s == '.')
1374 s++;
1375 while (*s && *s != '.')
1376 *p++ = *s++;
1377 *p = '\0';
1378 if (*s == '.')
1379 s++;
1380 if (strstr(s, "rodata") != NULL)
1381 strcat(p, "const ");
1382 else if (strstr(s, "data") != NULL)
1383 strcat(p, "data ");
1384 else
1385 strcat(p, " ");
Andy Shevchenkocbcf14a92010-08-17 13:36:40 +03001386 return r;
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001387 } else {
Randy Dunlap1f3aa902018-08-15 12:30:38 -07001388 return NOFAIL(strdup(""));
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001389 }
1390}
1391
1392static int is_function(Elf_Sym *sym)
1393{
1394 if (sym)
1395 return ELF_ST_TYPE(sym->st_info) == STT_FUNC;
1396 else
Sam Ravnborgf6667512008-02-06 21:51:18 +01001397 return -1;
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001398}
1399
Randy Dunlap00759c02011-03-15 14:13:47 -07001400static void print_section_list(const char * const list[20])
1401{
1402 const char *const *s = list;
1403
1404 while (*s) {
1405 fprintf(stderr, "%s", *s);
1406 s++;
1407 if (*s)
1408 fprintf(stderr, ", ");
1409 }
1410 fprintf(stderr, "\n");
1411}
1412
Quentin Casasnovas356ad532015-04-13 20:43:34 +09301413static inline void get_pretty_name(int is_func, const char** name, const char** name_p)
1414{
1415 switch (is_func) {
1416 case 0: *name = "variable"; *name_p = ""; break;
1417 case 1: *name = "function"; *name_p = "()"; break;
1418 default: *name = "(unknown reference)"; *name_p = ""; break;
1419 }
1420}
1421
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001422/*
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001423 * Print a warning about a section mismatch.
1424 * Try to find symbols near it so user can find it.
Sam Ravnborg4c8fbca2006-02-26 22:18:11 +01001425 * Check whitelist before warning - it may be a false positive.
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001426 */
Uwe Kleine-König0d2a6362010-01-30 16:56:20 +01001427static void report_sec_mismatch(const char *modname,
1428 const struct sectioncheck *mismatch,
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001429 const char *fromsec,
1430 unsigned long long fromaddr,
1431 const char *fromsym,
1432 int from_is_func,
1433 const char *tosec, const char *tosym,
1434 int to_is_func)
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001435{
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001436 const char *from, *from_p;
1437 const char *to, *to_p;
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001438 char *prl_from;
1439 char *prl_to;
Sam Ravnborgf6667512008-02-06 21:51:18 +01001440
Sam Ravnborge5f95c82008-02-02 18:57:18 +01001441 sec_mismatch_count++;
Sam Ravnborge5f95c82008-02-02 18:57:18 +01001442
Quentin Casasnovas356ad532015-04-13 20:43:34 +09301443 get_pretty_name(from_is_func, &from, &from_p);
1444 get_pretty_name(to_is_func, &to, &to_p);
1445
Geert Uytterhoeven7c0ac492008-02-05 11:38:49 +01001446 warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s "
1447 "to the %s %s:%s%s\n",
1448 modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
1449 tosym, to_p);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001450
Uwe Kleine-König0d2a6362010-01-30 16:56:20 +01001451 switch (mismatch->mismatch) {
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001452 case TEXT_TO_ANY_INIT:
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001453 prl_from = sec2annotation(fromsec);
1454 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001455 fprintf(stderr,
Sam Ravnborgf6667512008-02-06 21:51:18 +01001456 "The function %s%s() references\n"
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001457 "the %s %s%s%s.\n"
1458 "This is often because %s lacks a %s\n"
1459 "annotation or the annotation of %s is wrong.\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001460 prl_from, fromsym,
1461 to, prl_to, tosym, to_p,
1462 fromsym, prl_to, tosym);
1463 free(prl_from);
1464 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001465 break;
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001466 case DATA_TO_ANY_INIT: {
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001467 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001468 fprintf(stderr,
1469 "The variable %s references\n"
1470 "the %s %s%s%s\n"
1471 "If the reference is valid then annotate the\n"
Sam Ravnborg8b8b76c2009-06-06 00:18:05 +02001472 "variable with __init* or __refdata (see linux/init.h) "
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001473 "or name the variable:\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001474 fromsym, to, prl_to, tosym, to_p);
Randy Dunlap00759c02011-03-15 14:13:47 -07001475 print_section_list(mismatch->symbol_white_list);
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001476 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001477 break;
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001478 }
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001479 case TEXT_TO_ANY_EXIT:
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001480 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001481 fprintf(stderr,
1482 "The function %s() references a %s in an exit section.\n"
1483 "Often the %s %s%s has valid usage outside the exit section\n"
1484 "and the fix is to remove the %sannotation of %s.\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001485 fromsym, to, to, tosym, to_p, prl_to, tosym);
1486 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001487 break;
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001488 case DATA_TO_ANY_EXIT: {
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001489 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001490 fprintf(stderr,
1491 "The variable %s references\n"
1492 "the %s %s%s%s\n"
1493 "If the reference is valid then annotate the\n"
1494 "variable with __exit* (see linux/init.h) or "
1495 "name the variable:\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001496 fromsym, to, prl_to, tosym, to_p);
Randy Dunlap00759c02011-03-15 14:13:47 -07001497 print_section_list(mismatch->symbol_white_list);
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001498 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001499 break;
1500 }
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001501 case XXXINIT_TO_SOME_INIT:
1502 case XXXEXIT_TO_SOME_EXIT:
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001503 prl_from = sec2annotation(fromsec);
1504 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001505 fprintf(stderr,
1506 "The %s %s%s%s references\n"
1507 "a %s %s%s%s.\n"
1508 "If %s is only used by %s then\n"
1509 "annotate %s with a matching annotation.\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001510 from, prl_from, fromsym, from_p,
1511 to, prl_to, tosym, to_p,
Geert Uytterhoevenb1d26752008-02-17 14:12:10 +01001512 tosym, fromsym, tosym);
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001513 free(prl_from);
1514 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001515 break;
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001516 case ANY_INIT_TO_ANY_EXIT:
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001517 prl_from = sec2annotation(fromsec);
1518 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001519 fprintf(stderr,
1520 "The %s %s%s%s references\n"
1521 "a %s %s%s%s.\n"
1522 "This is often seen when error handling "
1523 "in the init function\n"
1524 "uses functionality in the exit path.\n"
1525 "The fix is often to remove the %sannotation of\n"
1526 "%s%s so it may be used outside an exit section.\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001527 from, prl_from, fromsym, from_p,
1528 to, prl_to, tosym, to_p,
Andrew Morton5003bab2010-08-11 00:42:26 -07001529 prl_to, tosym, to_p);
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001530 free(prl_from);
1531 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001532 break;
Uwe Kleine-Königbbd3f4f2010-01-30 16:35:47 +01001533 case ANY_EXIT_TO_ANY_INIT:
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001534 prl_from = sec2annotation(fromsec);
1535 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001536 fprintf(stderr,
1537 "The %s %s%s%s references\n"
1538 "a %s %s%s%s.\n"
1539 "This is often seen when error handling "
1540 "in the exit function\n"
1541 "uses functionality in the init path.\n"
1542 "The fix is often to remove the %sannotation of\n"
1543 "%s%s so it may be used outside an init section.\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001544 from, prl_from, fromsym, from_p,
1545 to, prl_to, tosym, to_p,
1546 prl_to, tosym, to_p);
1547 free(prl_from);
1548 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001549 break;
1550 case EXPORT_TO_INIT_EXIT:
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001551 prl_to = sec2annotation(tosec);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001552 fprintf(stderr,
1553 "The symbol %s is exported and annotated %s\n"
1554 "Fix this by removing the %sannotation of %s "
1555 "or drop the export.\n",
Alexey Fomenko37ed19d2010-08-09 17:20:24 -07001556 tosym, prl_to, prl_to, tosym);
1557 free(prl_to);
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001558 break;
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301559 case EXTABLE_TO_NON_TEXT:
1560 fatal("There's a special handler for this mismatch type, "
1561 "we should never get here.");
1562 break;
Sam Ravnborg588ccd72008-01-24 21:12:37 +01001563 }
1564 fprintf(stderr, "\n");
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001565}
1566
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301567static void default_mismatch_handler(const char *modname, struct elf_info *elf,
1568 const struct sectioncheck* const mismatch,
1569 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
1570{
1571 const char *tosec;
1572 Elf_Sym *to;
1573 Elf_Sym *from;
1574 const char *tosym;
1575 const char *fromsym;
1576
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301577 from = find_elf_symbol2(elf, r->r_offset, fromsec);
1578 fromsym = sym_name(elf, from);
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301579
Masahiro Yamadad62c4762018-05-09 18:50:38 +09001580 if (strstarts(fromsym, "reference___initcall"))
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301581 return;
1582
Quentin Casasnovasc7a65e02015-04-13 20:43:45 +09301583 tosec = sec_name(elf, get_secindex(elf, sym));
1584 to = find_elf_symbol(elf, r->r_addend, sym);
1585 tosym = sym_name(elf, to);
1586
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301587 /* check whitelist - we may ignore it */
1588 if (secref_whitelist(mismatch,
1589 fromsec, fromsym, tosec, tosym)) {
1590 report_sec_mismatch(modname, mismatch,
1591 fromsec, r->r_offset, fromsym,
1592 is_function(from), tosec, tosym,
1593 is_function(to));
1594 }
1595}
1596
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301597static int is_executable_section(struct elf_info* elf, unsigned int section_index)
1598{
1599 if (section_index > elf->num_sections)
1600 fatal("section_index is outside elf->num_sections!\n");
1601
1602 return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR);
1603}
1604
1605/*
1606 * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size()
1607 * to know the sizeof(struct exception_table_entry) for the target architecture.
1608 */
1609static unsigned int extable_entry_size = 0;
Quentin Casasnovase84048a2015-04-16 13:05:36 +09301610static void find_extable_entry_size(const char* const sec, const Elf_Rela* r)
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301611{
1612 /*
1613 * If we're currently checking the second relocation within __ex_table,
1614 * that relocation offset tells us the offsetof(struct
1615 * exception_table_entry, fixup) which is equal to sizeof(struct
1616 * exception_table_entry) divided by two. We use that to our advantage
1617 * since there's no portable way to get that size as every architecture
1618 * seems to go with different sized types. Not pretty but better than
1619 * hard-coding the size for every architecture..
1620 */
Quentin Casasnovase84048a2015-04-16 13:05:36 +09301621 if (!extable_entry_size)
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301622 extable_entry_size = r->r_offset * 2;
1623}
Quentin Casasnovase84048a2015-04-16 13:05:36 +09301624
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301625static inline bool is_extable_fault_address(Elf_Rela *r)
1626{
Quentin Casasnovasd3df4de2015-04-16 13:03:32 +09301627 /*
1628 * extable_entry_size is only discovered after we've handled the
1629 * _second_ relocation in __ex_table, so only abort when we're not
1630 * handling the first reloc and extable_entry_size is zero.
1631 */
1632 if (r->r_offset && extable_entry_size == 0)
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301633 fatal("extable_entry size hasn't been discovered!\n");
1634
1635 return ((r->r_offset == 0) ||
1636 (r->r_offset % extable_entry_size == 0));
1637}
1638
Quentin Casasnovase84048a2015-04-16 13:05:36 +09301639#define is_second_extable_reloc(Start, Cur, Sec) \
1640 (((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0))
1641
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301642static void report_extable_warnings(const char* modname, struct elf_info* elf,
1643 const struct sectioncheck* const mismatch,
1644 Elf_Rela* r, Elf_Sym* sym,
1645 const char* fromsec, const char* tosec)
1646{
1647 Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec);
1648 const char* fromsym_name = sym_name(elf, fromsym);
1649 Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym);
1650 const char* tosym_name = sym_name(elf, tosym);
1651 const char* from_pretty_name;
1652 const char* from_pretty_name_p;
1653 const char* to_pretty_name;
1654 const char* to_pretty_name_p;
1655
1656 get_pretty_name(is_function(fromsym),
1657 &from_pretty_name, &from_pretty_name_p);
1658 get_pretty_name(is_function(tosym),
1659 &to_pretty_name, &to_pretty_name_p);
1660
1661 warn("%s(%s+0x%lx): Section mismatch in reference"
1662 " from the %s %s%s to the %s %s:%s%s\n",
1663 modname, fromsec, (long)r->r_offset, from_pretty_name,
1664 fromsym_name, from_pretty_name_p,
1665 to_pretty_name, tosec, tosym_name, to_pretty_name_p);
1666
1667 if (!match(tosec, mismatch->bad_tosec) &&
1668 is_executable_section(elf, get_secindex(elf, sym)))
1669 fprintf(stderr,
1670 "The relocation at %s+0x%lx references\n"
1671 "section \"%s\" which is not in the list of\n"
1672 "authorized sections. If you're adding a new section\n"
1673 "and/or if this reference is valid, add \"%s\" to the\n"
1674 "list of authorized sections to jump to on fault.\n"
1675 "This can be achieved by adding \"%s\" to \n"
1676 "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n",
1677 fromsec, (long)r->r_offset, tosec, tosec, tosec);
1678}
1679
1680static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
1681 const struct sectioncheck* const mismatch,
1682 Elf_Rela* r, Elf_Sym* sym,
1683 const char *fromsec)
1684{
1685 const char* tosec = sec_name(elf, get_secindex(elf, sym));
1686
1687 sec_mismatch_count++;
1688
Masahiro Yamada46c7dd52019-02-01 13:50:45 +09001689 report_extable_warnings(modname, elf, mismatch, r, sym, fromsec, tosec);
Quentin Casasnovas52dc0592015-04-13 20:52:53 +09301690
1691 if (match(tosec, mismatch->bad_tosec))
1692 fatal("The relocation at %s+0x%lx references\n"
1693 "section \"%s\" which is black-listed.\n"
1694 "Something is seriously wrong and should be fixed.\n"
1695 "You might get more information about where this is\n"
1696 "coming from by using scripts/check_extable.sh %s\n",
1697 fromsec, (long)r->r_offset, tosec, modname);
1698 else if (!is_executable_section(elf, get_secindex(elf, sym))) {
1699 if (is_extable_fault_address(r))
1700 fatal("The relocation at %s+0x%lx references\n"
1701 "section \"%s\" which is not executable, IOW\n"
1702 "it is not possible for the kernel to fault\n"
1703 "at that address. Something is seriously wrong\n"
1704 "and should be fixed.\n",
1705 fromsec, (long)r->r_offset, tosec);
1706 else
1707 fatal("The relocation at %s+0x%lx references\n"
1708 "section \"%s\" which is not executable, IOW\n"
1709 "the kernel will fault if it ever tries to\n"
1710 "jump to it. Something is seriously wrong\n"
1711 "and should be fixed.\n",
1712 fromsec, (long)r->r_offset, tosec);
1713 }
1714}
1715
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001716static void check_section_mismatch(const char *modname, struct elf_info *elf,
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001717 Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001718{
Luis de Bethencourt0cad61d2018-01-16 13:21:29 +00001719 const char *tosec = sec_name(elf, get_secindex(elf, sym));
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301720 const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec);
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001721
Uwe Kleine-König0d2a6362010-01-30 16:56:20 +01001722 if (mismatch) {
Quentin Casasnovas644e8f12015-04-13 20:43:17 +09301723 if (mismatch->handler)
1724 mismatch->handler(modname, elf, mismatch,
1725 r, sym, fromsec);
1726 else
1727 default_mismatch_handler(modname, elf, mismatch,
1728 r, sym, fromsec);
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001729 }
1730}
1731
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001732static unsigned int *reloc_location(struct elf_info *elf,
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001733 Elf_Shdr *sechdr, Elf_Rela *r)
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001734{
Masahiro Yamadad2e4d052020-05-25 14:47:04 +09001735 return sym_get_data_by_offset(elf, sechdr->sh_info, r->r_offset);
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001736}
1737
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001738static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001739{
1740 unsigned int r_typ = ELF_R_TYPE(r->r_info);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001741 unsigned int *location = reloc_location(elf, sechdr, r);
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001742
1743 switch (r_typ) {
1744 case R_386_32:
1745 r->r_addend = TO_NATIVE(*location);
1746 break;
1747 case R_386_PC32:
1748 r->r_addend = TO_NATIVE(*location) + 4;
1749 /* For CONFIG_RELOCATABLE=y */
1750 if (elf->hdr->e_type == ET_EXEC)
1751 r->r_addend += r->r_offset;
1752 break;
1753 }
1754 return 0;
1755}
1756
Tony Lindgren6e2e3402012-02-14 21:58:56 +01001757#ifndef R_ARM_CALL
1758#define R_ARM_CALL 28
1759#endif
1760#ifndef R_ARM_JUMP24
1761#define R_ARM_JUMP24 29
1762#endif
1763
David A. Longc9698e52014-02-14 22:41:18 +01001764#ifndef R_ARM_THM_CALL
1765#define R_ARM_THM_CALL 10
1766#endif
1767#ifndef R_ARM_THM_JUMP24
1768#define R_ARM_THM_JUMP24 30
1769#endif
1770#ifndef R_ARM_THM_JUMP19
1771#define R_ARM_THM_JUMP19 51
1772#endif
1773
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001774static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
Sam Ravnborg56a974f2007-07-16 22:39:35 +02001775{
1776 unsigned int r_typ = ELF_R_TYPE(r->r_info);
1777
1778 switch (r_typ) {
1779 case R_ARM_ABS32:
1780 /* From ARM ABI: (S + A) | T */
Sam Ravnborgdf578e72008-01-11 19:17:15 +01001781 r->r_addend = (int)(long)
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001782 (elf->symtab_start + ELF_R_SYM(r->r_info));
Sam Ravnborg56a974f2007-07-16 22:39:35 +02001783 break;
1784 case R_ARM_PC24:
Tony Lindgren6e2e3402012-02-14 21:58:56 +01001785 case R_ARM_CALL:
1786 case R_ARM_JUMP24:
David A. Longc9698e52014-02-14 22:41:18 +01001787 case R_ARM_THM_CALL:
1788 case R_ARM_THM_JUMP24:
1789 case R_ARM_THM_JUMP19:
Sam Ravnborg56a974f2007-07-16 22:39:35 +02001790 /* From ARM ABI: ((S + A) | T) - P */
Sam Ravnborgdf578e72008-01-11 19:17:15 +01001791 r->r_addend = (int)(long)(elf->hdr +
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001792 sechdr->sh_offset +
1793 (r->r_offset - sechdr->sh_addr));
Sam Ravnborg56a974f2007-07-16 22:39:35 +02001794 break;
1795 default:
1796 return 1;
1797 }
1798 return 0;
1799}
1800
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001801static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001802{
1803 unsigned int r_typ = ELF_R_TYPE(r->r_info);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001804 unsigned int *location = reloc_location(elf, sechdr, r);
Atsushi Nemotoae4ac122007-05-22 18:27:39 +09001805 unsigned int inst;
1806
1807 if (r_typ == R_MIPS_HI16)
1808 return 1; /* skip this */
1809 inst = TO_NATIVE(*location);
1810 switch (r_typ) {
1811 case R_MIPS_LO16:
1812 r->r_addend = inst & 0xffff;
1813 break;
1814 case R_MIPS_26:
1815 r->r_addend = (inst & 0x03ffffff) << 2;
1816 break;
1817 case R_MIPS_32:
1818 r->r_addend = inst;
1819 break;
1820 }
1821 return 0;
1822}
1823
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001824static void section_rela(const char *modname, struct elf_info *elf,
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001825 Elf_Shdr *sechdr)
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001826{
1827 Elf_Sym *sym;
1828 Elf_Rela *rela;
1829 Elf_Rela r;
1830 unsigned int r_sym;
1831 const char *fromsec;
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001832
Sam Ravnborgff13f922008-01-23 19:54:27 +01001833 Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001834 Elf_Rela *stop = (void *)start + sechdr->sh_size;
1835
Sam Ravnborgff13f922008-01-23 19:54:27 +01001836 fromsec = sech_name(elf, sechdr);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001837 fromsec += strlen(".rela");
1838 /* if from section (name) is know good then skip it */
Anders Kaseorgb614a692009-04-23 16:49:33 -04001839 if (match(fromsec, section_white_list))
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001840 return;
Sam Ravnborge241a632008-01-28 20:13:13 +01001841
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001842 for (rela = start; rela < stop; rela++) {
1843 r.r_offset = TO_NATIVE(rela->r_offset);
1844#if KERNEL_ELFCLASS == ELFCLASS64
Sam Ravnborgff13f922008-01-23 19:54:27 +01001845 if (elf->hdr->e_machine == EM_MIPS) {
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001846 unsigned int r_typ;
1847 r_sym = ELF64_MIPS_R_SYM(rela->r_info);
1848 r_sym = TO_NATIVE(r_sym);
1849 r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
1850 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1851 } else {
1852 r.r_info = TO_NATIVE(rela->r_info);
1853 r_sym = ELF_R_SYM(r.r_info);
1854 }
1855#else
1856 r.r_info = TO_NATIVE(rela->r_info);
1857 r_sym = ELF_R_SYM(r.r_info);
1858#endif
1859 r.r_addend = TO_NATIVE(rela->r_addend);
1860 sym = elf->symtab_start + r_sym;
1861 /* Skip special sections */
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001862 if (is_shndx_special(sym->st_shndx))
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001863 continue;
Quentin Casasnovase84048a2015-04-16 13:05:36 +09301864 if (is_second_extable_reloc(start, rela, fromsec))
1865 find_extable_entry_size(fromsec, &r);
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001866 check_section_mismatch(modname, elf, &r, sym, fromsec);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001867 }
1868}
1869
1870static void section_rel(const char *modname, struct elf_info *elf,
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001871 Elf_Shdr *sechdr)
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001872{
1873 Elf_Sym *sym;
1874 Elf_Rel *rel;
1875 Elf_Rela r;
1876 unsigned int r_sym;
1877 const char *fromsec;
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001878
Sam Ravnborgff13f922008-01-23 19:54:27 +01001879 Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001880 Elf_Rel *stop = (void *)start + sechdr->sh_size;
1881
Sam Ravnborgff13f922008-01-23 19:54:27 +01001882 fromsec = sech_name(elf, sechdr);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001883 fromsec += strlen(".rel");
1884 /* if from section (name) is know good then skip it */
Anders Kaseorgb614a692009-04-23 16:49:33 -04001885 if (match(fromsec, section_white_list))
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001886 return;
1887
1888 for (rel = start; rel < stop; rel++) {
1889 r.r_offset = TO_NATIVE(rel->r_offset);
1890#if KERNEL_ELFCLASS == ELFCLASS64
Sam Ravnborgff13f922008-01-23 19:54:27 +01001891 if (elf->hdr->e_machine == EM_MIPS) {
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001892 unsigned int r_typ;
1893 r_sym = ELF64_MIPS_R_SYM(rel->r_info);
1894 r_sym = TO_NATIVE(r_sym);
1895 r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
1896 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1897 } else {
1898 r.r_info = TO_NATIVE(rel->r_info);
1899 r_sym = ELF_R_SYM(r.r_info);
1900 }
1901#else
1902 r.r_info = TO_NATIVE(rel->r_info);
1903 r_sym = ELF_R_SYM(r.r_info);
1904#endif
1905 r.r_addend = 0;
Sam Ravnborgff13f922008-01-23 19:54:27 +01001906 switch (elf->hdr->e_machine) {
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001907 case EM_386:
1908 if (addend_386_rel(elf, sechdr, &r))
1909 continue;
1910 break;
1911 case EM_ARM:
1912 if (addend_arm_rel(elf, sechdr, &r))
1913 continue;
1914 break;
1915 case EM_MIPS:
1916 if (addend_mips_rel(elf, sechdr, &r))
1917 continue;
1918 break;
1919 }
1920 sym = elf->symtab_start + r_sym;
1921 /* Skip special sections */
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001922 if (is_shndx_special(sym->st_shndx))
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001923 continue;
Quentin Casasnovase84048a2015-04-16 13:05:36 +09301924 if (is_second_extable_reloc(start, rel, fromsec))
1925 find_extable_entry_size(fromsec, &r);
Sam Ravnborg58fb0d42008-01-23 21:13:50 +01001926 check_section_mismatch(modname, elf, &r, sym, fromsec);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001927 }
1928}
1929
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001930/**
1931 * A module includes a number of sections that are discarded
1932 * either when loaded or when used as built-in.
1933 * For loaded modules all functions marked __init and all data
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04001934 * marked __initdata will be discarded when the module has been initialized.
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001935 * Likewise for modules used built-in the sections marked __exit
1936 * are discarded because __exit marked function are supposed to be called
Ben Dooks32be1d22008-07-29 22:33:44 -07001937 * only when a module is unloaded which never happens for built-in modules.
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001938 * The check_sec_ref() function traverses all relocation records
1939 * to find all references to a section that reference a section that will
1940 * be discarded and warns about it.
1941 **/
1942static void check_sec_ref(struct module *mod, const char *modname,
Masahiro Yamadabb66fc62014-06-10 19:08:13 +09001943 struct elf_info *elf)
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001944{
1945 int i;
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001946 Elf_Shdr *sechdrs = elf->sechdrs;
Sam Ravnborg62070fa2006-03-03 16:46:04 +01001947
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001948 /* Walk through all sections */
Denys Vlasenko1ce53ad2010-07-29 01:47:53 +02001949 for (i = 0; i < elf->num_sections; i++) {
Anders Kaseorgb614a692009-04-23 16:49:33 -04001950 check_section(modname, elf, &elf->sechdrs[i]);
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001951 /* We want to process only relocation sections and not .init */
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001952 if (sechdrs[i].sh_type == SHT_RELA)
Sam Ravnborg10668222008-01-13 22:21:31 +01001953 section_rela(modname, elf, &elf->sechdrs[i]);
Sam Ravnborg5b24c072008-01-18 21:49:29 +01001954 else if (sechdrs[i].sh_type == SHT_REL)
Sam Ravnborg10668222008-01-13 22:21:31 +01001955 section_rel(modname, elf, &elf->sechdrs[i]);
Sam Ravnborgb39927c2006-02-17 22:42:02 +01001956 }
1957}
1958
Andi Kleen7d02b492014-02-08 09:01:12 +01001959static char *remove_dot(char *s)
1960{
Michal Nazarewiczfcd38ed2014-07-27 07:27:01 +09301961 size_t n = strcspn(s, ".");
Andi Kleen7d02b492014-02-08 09:01:12 +01001962
Michal Nazarewiczfcd38ed2014-07-27 07:27:01 +09301963 if (n && s[n]) {
1964 size_t m = strspn(s + n + 1, "0123456789");
1965 if (m && (s[n + m] == '.' || s[n + m] == 0))
Andi Kleen7d02b492014-02-08 09:01:12 +01001966 s[n] = 0;
Sami Tolvanen7ac204b2020-12-11 10:46:27 -08001967
1968 /* strip trailing .lto */
1969 if (strends(s, ".lto"))
1970 s[strlen(s) - 4] = '\0';
Andi Kleen7d02b492014-02-08 09:01:12 +01001971 }
1972 return s;
1973}
1974
Masahiro Yamada8b185742018-05-09 18:50:40 +09001975static void read_symbols(const char *modname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976{
1977 const char *symname;
1978 char *version;
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02001979 char *license;
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01001980 char *namespace;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 struct module *mod;
1982 struct elf_info info = { };
1983 Elf_Sym *sym;
1984
Sam Ravnborg85bd2fd2007-02-26 15:33:52 +01001985 if (!parse_elf(&info, modname))
1986 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
Masahiro Yamadaa82f7942020-06-01 14:57:29 +09001988 {
1989 char *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990
Masahiro Yamadaa82f7942020-06-01 14:57:29 +09001991 /* strip trailing .o */
1992 tmp = NOFAIL(strdup(modname));
1993 tmp[strlen(tmp) - 2] = '\0';
Sami Tolvanen7ac204b2020-12-11 10:46:27 -08001994 /* strip trailing .lto */
1995 if (strends(tmp, ".lto"))
1996 tmp[strlen(tmp) - 4] = '\0';
Masahiro Yamadaa82f7942020-06-01 14:57:29 +09001997 mod = new_module(tmp);
1998 free(tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 }
2000
Masahiro Yamada5a438af2020-06-01 14:57:26 +09002001 if (!mod->is_vmlinux) {
Masahiro Yamada4ddea2f2020-06-01 14:57:16 +09002002 license = get_modinfo(&info, "license");
2003 if (!license)
Masahiro Yamada1d6cd3922020-12-01 19:34:16 +09002004 error("missing MODULE_LICENSE() in %s\n", modname);
Masahiro Yamada4ddea2f2020-06-01 14:57:16 +09002005 while (license) {
2006 if (license_is_gpl_compatible(license))
2007 mod->gpl_compatible = 1;
2008 else {
2009 mod->gpl_compatible = 0;
2010 break;
2011 }
2012 license = get_next_modinfo(&info, "license", license);
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002013 }
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002014
Masahiro Yamada4ddea2f2020-06-01 14:57:16 +09002015 namespace = get_modinfo(&info, "import_ns");
2016 while (namespace) {
2017 add_namespace(&mod->imported_namespaces, namespace);
2018 namespace = get_next_modinfo(&info, "import_ns",
2019 namespace);
2020 }
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002021 }
2022
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
Andi Kleen7d02b492014-02-08 09:01:12 +01002024 symname = remove_dot(info.strtab + sym->st_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
Masahiro Yamada9bd2a092019-11-15 02:42:23 +09002026 handle_symbol(mod, &info, sym, symname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 handle_moddevtable(mod, &info, sym, symname);
2028 }
Denis Efremov15bfc232019-08-01 09:06:57 +03002029
Matthias Maennich69923202019-10-18 10:31:42 +01002030 for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
2031 symname = remove_dot(info.strtab + sym->st_name);
2032
Masahiro Yamada17436942019-11-15 02:42:24 +09002033 /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */
Matthias Maennich69923202019-10-18 10:31:42 +01002034 if (strstarts(symname, "__kstrtabns_"))
2035 sym_update_namespace(symname + strlen("__kstrtabns_"),
2036 namespace_from_kstrtabns(&info,
2037 sym));
Masahiro Yamada17436942019-11-15 02:42:24 +09002038
2039 if (strstarts(symname, "__crc_"))
2040 handle_modversion(mod, &info, sym,
2041 symname + strlen("__crc_"));
Matthias Maennich69923202019-10-18 10:31:42 +01002042 }
2043
Denis Efremov15bfc232019-08-01 09:06:57 +03002044 // check for static EXPORT_SYMBOL_* functions && global vars
2045 for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
2046 unsigned char bind = ELF_ST_BIND(sym->st_info);
2047
2048 if (bind == STB_GLOBAL || bind == STB_WEAK) {
2049 struct symbol *s =
2050 find_symbol(remove_dot(info.strtab +
2051 sym->st_name));
2052
2053 if (s)
2054 s->is_static = 0;
2055 }
2056 }
2057
Masahiro Yamada467b82d2020-06-01 14:57:22 +09002058 check_sec_ref(mod, modname, &info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
Masahiro Yamada5a438af2020-06-01 14:57:26 +09002060 if (!mod->is_vmlinux) {
Masahiro Yamada4ddea2f2020-06-01 14:57:16 +09002061 version = get_modinfo(&info, "version");
2062 if (version || all_versions)
2063 get_src_version(modname, mod->srcversion,
2064 sizeof(mod->srcversion) - 1);
2065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
2067 parse_elf_finish(&info);
2068
Rusty Russell8c8ef422009-03-31 13:05:34 -06002069 /* Our trick to get versioning for module struct etc. - it's
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 * never passed as an argument to an exported function, so
2071 * the automatic versioning doesn't pick it up, but it's really
2072 * important anyhow */
2073 if (modversions)
Rusty Russell8c8ef422009-03-31 13:05:34 -06002074 mod->unres = alloc_symbol("module_layout", 0, mod->unres);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075}
2076
Rusty Russell712f9b42013-04-04 17:37:38 +10302077static void read_symbols_from_files(const char *filename)
2078{
2079 FILE *in = stdin;
2080 char fname[PATH_MAX];
2081
2082 if (strcmp(filename, "-") != 0) {
2083 in = fopen(filename, "r");
2084 if (!in)
2085 fatal("Can't open filenames file %s: %m", filename);
2086 }
2087
2088 while (fgets(fname, PATH_MAX, in) != NULL) {
2089 if (strends(fname, "\n"))
2090 fname[strlen(fname)-1] = '\0';
2091 read_symbols(fname);
2092 }
2093
2094 if (in != stdin)
2095 fclose(in);
2096}
2097
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098#define SZ 500
2099
2100/* We first write the generated file into memory using the
2101 * following helper, then compare to the file on disk and
2102 * only update the later if anything changed */
2103
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002104void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
2105 const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106{
2107 char tmp[SZ];
2108 int len;
2109 va_list ap;
Sam Ravnborg62070fa2006-03-03 16:46:04 +01002110
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 va_start(ap, fmt);
2112 len = vsnprintf(tmp, SZ, fmt, ap);
Sam Ravnborg7670f0232006-03-16 23:04:08 -08002113 buf_write(buf, tmp, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 va_end(ap);
2115}
2116
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002117void buf_write(struct buffer *buf, const char *s, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118{
2119 if (buf->size - buf->pos < len) {
Sam Ravnborg7670f0232006-03-16 23:04:08 -08002120 buf->size += len + SZ;
Randy Dunlap1f3aa902018-08-15 12:30:38 -07002121 buf->p = NOFAIL(realloc(buf->p, buf->size));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 }
2123 strncpy(buf->p + buf->pos, s, len);
2124 buf->pos += len;
2125}
2126
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002127static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
2128{
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002129 switch (exp) {
2130 case export_gpl:
Masahiro Yamadad6d692f2020-12-01 19:34:17 +09002131 error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
Masahiro Yamada1be5fa62020-06-01 14:57:25 +09002132 m, s);
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002133 break;
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002134 case export_plain:
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002135 case export_unknown:
2136 /* ignore */
2137 break;
2138 }
2139}
2140
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002141static void check_exports(struct module *mod)
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002142{
2143 struct symbol *s, *exp;
2144
2145 for (s = mod->unres; s; s = s->next) {
Andrew Morton6449bd62006-06-09 20:45:06 -07002146 const char *basename;
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002147 exp = find_symbol(s->name);
Masahiro Yamada3b415282018-11-23 16:57:23 +09002148 if (!exp || exp->module == mod) {
Masahiro Yamada4475dff2021-03-26 03:54:11 +09002149 if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS)
Jessica Yu93c95e52020-03-06 17:02:05 +01002150 modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
2151 "\"%s\" [%s.ko] undefined!\n",
2152 s->name, mod->name);
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002153 continue;
Masahiro Yamada3b415282018-11-23 16:57:23 +09002154 }
Andrew Morton6449bd62006-06-09 20:45:06 -07002155 basename = strrchr(mod->name, '/');
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002156 if (basename)
2157 basename++;
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002158 else
2159 basename = mod->name;
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002160
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002161 if (exp->namespace &&
2162 !module_imports_namespace(mod, exp->namespace)) {
Jessica Yu54b77842020-03-06 17:02:06 +01002163 modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,
2164 "module %s uses symbol %s from namespace %s, but does not import it.\n",
2165 basename, exp->name, exp->namespace);
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002166 add_namespace(&mod->missing_namespaces, exp->namespace);
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002167 }
2168
Sam Ravnborgc96fca22006-07-01 11:44:23 +02002169 if (!mod->gpl_compatible)
2170 check_for_gpl_usage(exp->export, basename, exp->name);
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002171 }
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002172}
2173
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002174static void check_modname_len(struct module *mod)
Wanlong Gao4fd3e4e2017-06-30 22:07:03 +08002175{
2176 const char *mod_name;
2177
2178 mod_name = strrchr(mod->name, '/');
2179 if (mod_name == NULL)
2180 mod_name = mod->name;
2181 else
2182 mod_name++;
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002183 if (strlen(mod_name) >= MODULE_NAME_LEN)
Masahiro Yamadabc72d722020-12-01 19:34:14 +09002184 error("module name is too long [%s.ko]\n", mod->name);
Wanlong Gao4fd3e4e2017-06-30 22:07:03 +08002185}
2186
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002187/**
2188 * Header for the generated file
2189 **/
2190static void add_header(struct buffer *b, struct module *mod)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191{
2192 buf_printf(b, "#include <linux/module.h>\n");
Vincenzo Frascinof58dd032020-03-20 14:53:41 +00002193 /*
2194 * Include build-salt.h after module.h in order to
2195 * inherit the definitions.
2196 */
Leon Romanovsky51161bf2020-04-19 18:55:06 +03002197 buf_printf(b, "#define INCLUDE_VERMAGIC\n");
Vincenzo Frascinof58dd032020-03-20 14:53:41 +00002198 buf_printf(b, "#include <linux/build-salt.h>\n");
Yonghong Song1fdd7432021-04-01 16:27:23 -07002199 buf_printf(b, "#include <linux/elfnote-lto.h>\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 buf_printf(b, "#include <linux/vermagic.h>\n");
2201 buf_printf(b, "#include <linux/compiler.h>\n");
2202 buf_printf(b, "\n");
Laura Abbott9afb7192018-07-05 17:49:37 -07002203 buf_printf(b, "BUILD_SALT;\n");
Yonghong Song1fdd7432021-04-01 16:27:23 -07002204 buf_printf(b, "BUILD_LTO_INFO;\n");
Laura Abbott9afb7192018-07-05 17:49:37 -07002205 buf_printf(b, "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
Kees Cook3e2e8572017-04-21 15:35:27 -07002207 buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 buf_printf(b, "\n");
Andi Kleene0f244c2013-10-23 10:57:58 +10302209 buf_printf(b, "__visible struct module __this_module\n");
Joe Perches33def842020-10-21 19:36:07 -07002210 buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n");
Greg Kroah-Hartman3c7ec942012-04-25 11:10:15 -07002211 buf_printf(b, "\t.name = KBUILD_MODNAME,\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 if (mod->has_init)
Greg Kroah-Hartman3c7ec942012-04-25 11:10:15 -07002213 buf_printf(b, "\t.init = init_module,\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 if (mod->has_cleanup)
2215 buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
Greg Kroah-Hartman3c7ec942012-04-25 11:10:15 -07002216 "\t.exit = cleanup_module,\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 "#endif\n");
Greg Kroah-Hartman3c7ec942012-04-25 11:10:15 -07002218 buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 buf_printf(b, "};\n");
2220}
2221
Ben Hutchings2449b8b2011-10-24 15:12:28 +02002222static void add_intree_flag(struct buffer *b, int is_intree)
2223{
2224 if (is_intree)
2225 buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
2226}
2227
Andi Kleencaf75012018-01-25 15:50:28 -08002228/* Cannot check for assembler */
2229static void add_retpoline(struct buffer *b)
2230{
WANG Chaoe4f35892018-12-11 00:37:25 +08002231 buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n");
Andi Kleencaf75012018-01-25 15:50:28 -08002232 buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n");
2233 buf_printf(b, "#endif\n");
2234}
2235
Trevor Keith5c725132009-09-22 16:43:38 -07002236static void add_staging_flag(struct buffer *b, const char *name)
Greg Kroah-Hartmana9860bf2008-09-24 14:46:44 -07002237{
Masahiro Yamadad62c4762018-05-09 18:50:38 +09002238 if (strstarts(name, "drivers/staging"))
Greg Kroah-Hartmana9860bf2008-09-24 14:46:44 -07002239 buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
2240}
2241
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002242/**
2243 * Record CRCs for unresolved symbols
2244 **/
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002245static void add_versions(struct buffer *b, struct module *mod)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246{
2247 struct symbol *s, *exp;
2248
2249 for (s = mod->unres; s; s = s->next) {
2250 exp = find_symbol(s->name);
Masahiro Yamada3b415282018-11-23 16:57:23 +09002251 if (!exp || exp->module == mod)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 s->module = exp->module;
2254 s->crc_valid = exp->crc_valid;
2255 s->crc = exp->crc;
2256 }
2257
2258 if (!modversions)
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002259 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260
2261 buf_printf(b, "\n");
2262 buf_printf(b, "static const struct modversion_info ____versions[]\n");
Joe Perches33def842020-10-21 19:36:07 -07002263 buf_printf(b, "__used __section(\"__versions\") = {\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
2265 for (s = mod->unres; s; s = s->next) {
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002266 if (!s->module)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 if (!s->crc_valid) {
Sam Ravnborgcb805142006-01-28 16:57:26 +01002269 warn("\"%s\" [%s.ko] has no CRC!\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 s->name, mod->name);
2271 continue;
2272 }
Takashi Iwai5cfb2032015-08-08 15:16:20 +09302273 if (strlen(s->name) >= MODULE_NAME_LEN) {
Masahiro Yamadabc72d722020-12-01 19:34:14 +09002274 error("too long symbol \"%s\" [%s.ko]\n",
2275 s->name, mod->name);
Takashi Iwai5cfb2032015-08-08 15:16:20 +09302276 break;
2277 }
Masahiro Yamadab2c5cdc2018-05-09 16:23:45 +09002278 buf_printf(b, "\t{ %#8x, \"%s\" },\n",
James Hogana4b6a772013-03-18 19:38:56 +10302279 s->crc, s->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 }
2281
2282 buf_printf(b, "};\n");
2283}
2284
Masahiro Yamadad2665ca2018-11-23 16:57:21 +09002285static void add_depends(struct buffer *b, struct module *mod)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286{
2287 struct symbol *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 int first = 1;
2289
Masahiro Yamadad2665ca2018-11-23 16:57:21 +09002290 /* Clear ->seen flag of modules that own symbols needed by this. */
2291 for (s = mod->unres; s; s = s->next)
2292 if (s->module)
Masahiro Yamada5a438af2020-06-01 14:57:26 +09002293 s->module->seen = s->module->is_vmlinux;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
2295 buf_printf(b, "\n");
Masahiro Yamada6df7e1e2019-09-09 20:34:22 +09002296 buf_printf(b, "MODULE_INFO(depends, \"");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 for (s = mod->unres; s; s = s->next) {
Sam Ravnborga61b2df2007-02-26 19:46:52 +01002298 const char *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 if (!s->module)
2300 continue;
2301
2302 if (s->module->seen)
2303 continue;
2304
2305 s->module->seen = 1;
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002306 p = strrchr(s->module->name, '/');
2307 if (p)
Sam Ravnborga61b2df2007-02-26 19:46:52 +01002308 p++;
2309 else
2310 p = s->module->name;
2311 buf_printf(b, "%s%s", first ? "" : ",", p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 first = 0;
2313 }
Masahiro Yamada6df7e1e2019-09-09 20:34:22 +09002314 buf_printf(b, "\");\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315}
2316
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002317static void add_srcversion(struct buffer *b, struct module *mod)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318{
2319 if (mod->srcversion[0]) {
2320 buf_printf(b, "\n");
2321 buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
2322 mod->srcversion);
2323 }
2324}
2325
Masahiro Yamada436b2ac2020-06-01 14:57:12 +09002326static void write_buf(struct buffer *b, const char *fname)
2327{
2328 FILE *file;
2329
2330 file = fopen(fname, "w");
2331 if (!file) {
2332 perror(fname);
2333 exit(1);
2334 }
2335 if (fwrite(b->p, 1, b->pos, file) != b->pos) {
2336 perror(fname);
2337 exit(1);
2338 }
2339 if (fclose(file) != 0) {
2340 perror(fname);
2341 exit(1);
2342 }
2343}
2344
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002345static void write_if_changed(struct buffer *b, const char *fname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346{
2347 char *tmp;
2348 FILE *file;
2349 struct stat st;
2350
2351 file = fopen(fname, "r");
2352 if (!file)
2353 goto write;
2354
2355 if (fstat(fileno(file), &st) < 0)
2356 goto close_write;
2357
2358 if (st.st_size != b->pos)
2359 goto close_write;
2360
2361 tmp = NOFAIL(malloc(b->pos));
2362 if (fread(tmp, 1, b->pos, file) != b->pos)
2363 goto free_write;
2364
2365 if (memcmp(tmp, b->p, b->pos) != 0)
2366 goto free_write;
2367
2368 free(tmp);
2369 fclose(file);
2370 return;
2371
2372 free_write:
2373 free(tmp);
2374 close_write:
2375 fclose(file);
2376 write:
Masahiro Yamada436b2ac2020-06-01 14:57:12 +09002377 write_buf(b, fname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378}
2379
Ram Paibd5cbce2006-06-08 22:12:53 -07002380/* parse Module.symvers file. line format:
Jessica Yu51900442020-03-11 18:01:20 +01002381 * 0x12345678<tab>symbol<tab>module<tab>export<tab>namespace
Ram Paibd5cbce2006-06-08 22:12:53 -07002382 **/
Masahiro Yamada52c34162020-06-01 14:57:05 +09002383static void read_dump(const char *fname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384{
Masahiro Yamada70f30cf2020-06-01 14:57:20 +09002385 char *buf, *pos, *line;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386
Masahiro Yamada70f30cf2020-06-01 14:57:20 +09002387 buf = read_text_file(fname);
2388 if (!buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 /* No symbol versions, silently ignore */
2390 return;
2391
Masahiro Yamada70f30cf2020-06-01 14:57:20 +09002392 pos = buf;
2393
2394 while ((line = get_line(&pos))) {
Jessica Yu51900442020-03-11 18:01:20 +01002395 char *symname, *namespace, *modname, *d, *export;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 unsigned int crc;
2397 struct module *mod;
Sam Ravnborg040fcc82006-01-28 22:15:55 +01002398 struct symbol *s;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
2400 if (!(symname = strchr(line, '\t')))
2401 goto fail;
2402 *symname++ = '\0';
Jessica Yu51900442020-03-11 18:01:20 +01002403 if (!(modname = strchr(symname, '\t')))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 goto fail;
2405 *modname++ = '\0';
Jessica Yu51900442020-03-11 18:01:20 +01002406 if (!(export = strchr(modname, '\t')))
2407 goto fail;
2408 *export++ = '\0';
2409 if (!(namespace = strchr(export, '\t')))
2410 goto fail;
2411 *namespace++ = '\0';
2412
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 crc = strtoul(line, &d, 16);
2414 if (*symname == '\0' || *modname == '\0' || *d != '\0')
2415 goto fail;
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002416 mod = find_module(modname);
2417 if (!mod) {
Jan Beulich0fa3a882009-03-12 12:28:30 +00002418 mod = new_module(modname);
Masahiro Yamada52c34162020-06-01 14:57:05 +09002419 mod->from_dump = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 }
Matthias Maennich9ae5bd12019-10-18 10:31:41 +01002421 s = sym_add_exported(symname, mod, export_no(export));
Denis Efremov15bfc232019-08-01 09:06:57 +03002422 s->is_static = 0;
Masahiro Yamada17436942019-11-15 02:42:24 +09002423 sym_set_crc(symname, crc);
Matthias Maennich9ae5bd12019-10-18 10:31:41 +01002424 sym_update_namespace(symname, namespace);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 }
Masahiro Yamada70f30cf2020-06-01 14:57:20 +09002426 free(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 return;
2428fail:
Masahiro Yamada70f30cf2020-06-01 14:57:20 +09002429 free(buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 fatal("parse error in symbol dump file\n");
2431}
2432
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002433static void write_dump(const char *fname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434{
2435 struct buffer buf = { };
2436 struct symbol *symbol;
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002437 const char *namespace;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 int n;
2439
2440 for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
2441 symbol = symbolhash[n];
2442 while (symbol) {
Masahiro Yamada69bc8d32021-03-26 03:54:09 +09002443 if (!symbol->module->from_dump) {
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002444 namespace = symbol->namespace;
2445 buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n",
2446 symbol->crc, symbol->name,
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002447 symbol->module->name,
Jessica Yu51900442020-03-11 18:01:20 +01002448 export_str(symbol->export),
2449 namespace ? namespace : "");
Matthias Maennichcb9b55d2019-09-06 11:32:28 +01002450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 symbol = symbol->next;
2452 }
2453 }
Masahiro Yamada436b2ac2020-06-01 14:57:12 +09002454 write_buf(&buf, fname);
Heinrich Schuchardtc7d47f22016-08-02 21:43:01 +02002455 free(buf.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456}
2457
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002458static void write_namespace_deps_files(const char *fname)
Matthias Maennich1d082772019-09-06 11:32:31 +01002459{
2460 struct module *mod;
2461 struct namespace_list *ns;
2462 struct buffer ns_deps_buf = {};
2463
2464 for (mod = modules; mod; mod = mod->next) {
Matthias Maennich1d082772019-09-06 11:32:31 +01002465
Masahiro Yamada0b19d542020-06-01 14:57:27 +09002466 if (mod->from_dump || !mod->missing_namespaces)
Matthias Maennich1d082772019-09-06 11:32:31 +01002467 continue;
2468
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002469 buf_printf(&ns_deps_buf, "%s.ko:", mod->name);
Matthias Maennich1d082772019-09-06 11:32:31 +01002470
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002471 for (ns = mod->missing_namespaces; ns; ns = ns->next)
2472 buf_printf(&ns_deps_buf, " %s", ns->namespace);
Matthias Maennich1d082772019-09-06 11:32:31 +01002473
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002474 buf_printf(&ns_deps_buf, "\n");
Matthias Maennich1d082772019-09-06 11:32:31 +01002475 }
Masahiro Yamada0241ea82019-11-07 00:19:59 +09002476
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002477 write_if_changed(&ns_deps_buf, fname);
Masahiro Yamada0241ea82019-11-07 00:19:59 +09002478 free(ns_deps_buf.p);
Matthias Maennich1d082772019-09-06 11:32:31 +01002479}
2480
Masahiro Yamada79247992020-06-01 14:57:07 +09002481struct dump_list {
2482 struct dump_list *next;
Richard Hacker2d04b5a2008-02-28 09:40:52 +01002483 const char *file;
2484};
2485
Sam Ravnborg5c3ead82006-01-28 17:19:35 +01002486int main(int argc, char **argv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487{
2488 struct module *mod;
2489 struct buffer buf = { };
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002490 char *missing_namespace_deps = NULL;
Rusty Russell712f9b42013-04-04 17:37:38 +10302491 char *dump_write = NULL, *files_source = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 int opt;
Denis Efremov15bfc232019-08-01 09:06:57 +03002493 int n;
Masahiro Yamada79247992020-06-01 14:57:07 +09002494 struct dump_list *dump_read_start = NULL;
2495 struct dump_list **dump_read_iter = &dump_read_start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
Masahiro Yamada467b82d2020-06-01 14:57:22 +09002497 while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) {
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002498 switch (opt) {
Richard Hacker2d04b5a2008-02-28 09:40:52 +01002499 case 'e':
2500 external_module = 1;
Masahiro Yamadae3fb4df2020-06-01 14:57:08 +09002501 break;
2502 case 'i':
Masahiro Yamada79247992020-06-01 14:57:07 +09002503 *dump_read_iter =
2504 NOFAIL(calloc(1, sizeof(**dump_read_iter)));
2505 (*dump_read_iter)->file = optarg;
2506 dump_read_iter = &(*dump_read_iter)->next;
Richard Hacker2d04b5a2008-02-28 09:40:52 +01002507 break;
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002508 case 'm':
2509 modversions = 1;
2510 break;
Guenter Roeckeed380f2013-09-23 15:23:54 +09302511 case 'n':
2512 ignore_missing_files = 1;
2513 break;
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002514 case 'o':
2515 dump_write = optarg;
2516 break;
2517 case 'a':
2518 all_versions = 1;
2519 break;
Rusty Russell712f9b42013-04-04 17:37:38 +10302520 case 'T':
2521 files_source = optarg;
2522 break;
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002523 case 'w':
2524 warn_unresolved = 1;
2525 break;
Nicolas Boichat47490ec2015-10-06 09:44:42 +10302526 case 'E':
Masahiro Yamadac7299d92020-12-01 19:34:18 +09002527 sec_mismatch_warn_only = false;
Nicolas Boichat47490ec2015-10-06 09:44:42 +10302528 break;
Jessica Yu54b77842020-03-06 17:02:06 +01002529 case 'N':
2530 allow_missing_ns_imports = 1;
2531 break;
Matthias Maennich1d082772019-09-06 11:32:31 +01002532 case 'd':
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002533 missing_namespace_deps = optarg;
Matthias Maennich1d082772019-09-06 11:32:31 +01002534 break;
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002535 default:
2536 exit(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 }
2538 }
2539
Masahiro Yamada79247992020-06-01 14:57:07 +09002540 while (dump_read_start) {
2541 struct dump_list *tmp;
Masahiro Yamada2beee862020-06-01 14:57:04 +09002542
Masahiro Yamada79247992020-06-01 14:57:07 +09002543 read_dump(dump_read_start->file);
2544 tmp = dump_read_start->next;
2545 free(dump_read_start);
2546 dump_read_start = tmp;
Richard Hacker2d04b5a2008-02-28 09:40:52 +01002547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Sam Ravnborgdf578e72008-01-11 19:17:15 +01002549 while (optind < argc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 read_symbols(argv[optind++]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
Rusty Russell712f9b42013-04-04 17:37:38 +10302552 if (files_source)
2553 read_symbols_from_files(files_source);
2554
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002555 for (mod = modules; mod; mod = mod->next) {
Mathias Kraused93e1712014-08-27 20:28:56 +09302556 char fname[PATH_MAX];
Andi Kleen666ab412007-11-22 03:43:10 +01002557
Masahiro Yamada0b19d542020-06-01 14:57:27 +09002558 if (mod->is_vmlinux || mod->from_dump)
Sam Ravnborgb817f6f2006-06-09 21:53:55 +02002559 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
2561 buf.pos = 0;
2562
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002563 check_modname_len(mod);
2564 check_exports(mod);
Matthias Maennich1d082772019-09-06 11:32:31 +01002565
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 add_header(&buf, mod);
Ben Hutchings2449b8b2011-10-24 15:12:28 +02002567 add_intree_flag(&buf, !external_module);
Andi Kleencaf75012018-01-25 15:50:28 -08002568 add_retpoline(&buf);
Greg Kroah-Hartmana9860bf2008-09-24 14:46:44 -07002569 add_staging_flag(&buf, mod->name);
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002570 add_versions(&buf, mod);
Masahiro Yamadad2665ca2018-11-23 16:57:21 +09002571 add_depends(&buf, mod);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 add_moddevtable(&buf, mod);
2573 add_srcversion(&buf, mod);
2574
2575 sprintf(fname, "%s.mod.c", mod->name);
2576 write_if_changed(&buf, fname);
2577 }
Matthias Maennich1d082772019-09-06 11:32:31 +01002578
Masahiro Yamadabbc55bd2019-10-29 21:38:07 +09002579 if (missing_namespace_deps)
2580 write_namespace_deps_files(missing_namespace_deps);
Matthias Maennich1d082772019-09-06 11:32:31 +01002581
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 if (dump_write)
2583 write_dump(dump_write);
Masahiro Yamadac7299d92020-12-01 19:34:18 +09002584 if (sec_mismatch_count && !sec_mismatch_warn_only)
2585 error("Section mismatches detected.\n"
Masahiro Yamada46c7dd52019-02-01 13:50:45 +09002586 "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
Denis Efremov15bfc232019-08-01 09:06:57 +03002587 for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
Masahiro Yamada47346e92019-09-24 21:07:40 +09002588 struct symbol *s;
Denis Efremov15bfc232019-08-01 09:06:57 +03002589
Masahiro Yamada47346e92019-09-24 21:07:40 +09002590 for (s = symbolhash[n]; s; s = s->next) {
Denis Efremov15bfc232019-08-01 09:06:57 +03002591 if (s->is_static)
Quentin Perretb9ed8472020-12-01 16:52:22 +00002592 error("\"%s\" [%s] is a static %s\n",
2593 s->name, s->module->name,
2594 export_str(s->export));
Denis Efremov15bfc232019-08-01 09:06:57 +03002595 }
2596 }
2597
Masahiro Yamada4475dff2021-03-26 03:54:11 +09002598 if (nr_unresolved > MAX_UNRESOLVED_REPORTS)
2599 warn("suppressed %u unresolved symbol warnings because there were too many)\n",
2600 nr_unresolved - MAX_UNRESOLVED_REPORTS);
2601
Heinrich Schuchardtc7d47f22016-08-02 21:43:01 +02002602 free(buf.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
Masahiro Yamada0fd3fba2020-12-01 19:34:15 +09002604 return error_occurred ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605}