Blame view
scripts/mod/modpost.c
57.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 |
/* Postprocess module symbol versions * * Copyright 2003 Kai Germaschewski * Copyright 2002-2004 Rusty Russell, IBM Corporation |
df578e7d8 kbuild: clean up ... |
5 |
* Copyright 2006-2008 Sam Ravnborg |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 |
* Based in part on module-init-tools/depmod.c,file2alias * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * Usage: modpost vmlinux module1.o module2.o ... */ |
b2e3e658b Linux Kernel Mark... |
13 14 |
#define _GNU_SOURCE #include <stdio.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <ctype.h> |
5003bab82 fix "scripts/mod/... |
16 |
#include <string.h> |
712f9b468 modpost: add -T o... |
17 |
#include <limits.h> |
d4ef1c30e modpost: minor cl... |
18 |
#include <stdbool.h> |
eed380f3f modpost: Optional... |
19 |
#include <errno.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include "modpost.h" |
5a865c060 Merge branch 'for... |
21 |
#include "../../include/generated/autoconf.h" |
b817f6fef kbuild: check lic... |
22 |
#include "../../include/linux/license.h" |
b92021b09 CONFIG_SYMBOL_PRE... |
23 |
#include "../../include/linux/export.h" |
9e1b9b807 module: make MODU... |
24 |
|
1da177e4c Linux-2.6.12-rc2 |
25 26 27 28 29 30 |
/* Are we using CONFIG_MODVERSIONS? */ int modversions = 0; /* Warn about undefined symbols? (do so if we have vmlinux) */ int have_vmlinux = 0; /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ static int all_versions = 0; |
040fcc819 kbuild: improved ... |
31 32 |
/* If we are modposting external module set to 1 */ static int external_module = 0; |
8d8d8289d kbuild: do not do... |
33 34 |
/* Warn about section mismatch in vmlinux if set to 1 */ static int vmlinux_section_warnings = 1; |
c53ddacdc kbuild: fail kern... |
35 36 |
/* Only warn about unresolved symbols */ static int warn_unresolved = 0; |
bd5cbcedf kbuild: export-ty... |
37 |
/* How a symbol is exported */ |
588ccd732 kbuild: add verbo... |
38 39 |
static int sec_mismatch_count = 0; static int sec_mismatch_verbose = 1; |
eed380f3f modpost: Optional... |
40 41 |
/* ignore missing files */ static int ignore_missing_files; |
588ccd732 kbuild: add verbo... |
42 |
|
c96fca213 kbuild: warn when... |
43 44 45 46 |
enum export { export_plain, export_unused, export_gpl, export_unused_gpl, export_gpl_future, export_unknown }; |
1da177e4c Linux-2.6.12-rc2 |
47 |
|
6d9a89ea4 kbuild: declare t... |
48 49 50 |
#define PRINTF __attribute__ ((format (printf, 1, 2))) PRINTF void fatal(const char *fmt, ...) |
1da177e4c Linux-2.6.12-rc2 |
51 52 53 54 55 56 57 58 59 60 61 |
{ va_list arglist; fprintf(stderr, "FATAL: "); va_start(arglist, fmt); vfprintf(stderr, fmt, arglist); va_end(arglist); exit(1); } |
6d9a89ea4 kbuild: declare t... |
62 |
PRINTF void warn(const char *fmt, ...) |
1da177e4c Linux-2.6.12-rc2 |
63 64 65 66 67 68 69 70 71 |
{ va_list arglist; fprintf(stderr, "WARNING: "); va_start(arglist, fmt); vfprintf(stderr, fmt, arglist); va_end(arglist); } |
6d9a89ea4 kbuild: declare t... |
72 |
PRINTF void merror(const char *fmt, ...) |
2a1166594 kbuild: distingui... |
73 74 75 76 77 78 79 80 81 |
{ va_list arglist; fprintf(stderr, "ERROR: "); va_start(arglist, fmt); vfprintf(stderr, fmt, arglist); va_end(arglist); } |
d4ef1c30e modpost: minor cl... |
82 83 84 85 86 87 88 |
static inline bool strends(const char *str, const char *postfix) { if (strlen(str) < strlen(postfix)) return false; return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; } |
040fcc819 kbuild: improved ... |
89 90 91 |
static int is_vmlinux(const char *modname) { const char *myname; |
df578e7d8 kbuild: clean up ... |
92 93 |
myname = strrchr(modname, '/'); if (myname) |
040fcc819 kbuild: improved ... |
94 95 96 |
myname++; else myname = modname; |
741f98fe2 kbuild: do sectio... |
97 98 |
return (strcmp(myname, "vmlinux") == 0) || (strcmp(myname, "vmlinux.o") == 0); |
040fcc819 kbuild: improved ... |
99 |
} |
1da177e4c Linux-2.6.12-rc2 |
100 101 |
void *do_nofail(void *ptr, const char *expr) { |
df578e7d8 kbuild: clean up ... |
102 |
if (!ptr) |
1da177e4c Linux-2.6.12-rc2 |
103 104 |
fatal("modpost: Memory allocation failure: %s. ", expr); |
df578e7d8 kbuild: clean up ... |
105 |
|
1da177e4c Linux-2.6.12-rc2 |
106 107 108 109 |
return ptr; } /* A list of all modules we processed */ |
1da177e4c Linux-2.6.12-rc2 |
110 |
static struct module *modules; |
5c3ead8c7 kbuild: apply Cod... |
111 |
static struct module *find_module(char *modname) |
1da177e4c Linux-2.6.12-rc2 |
112 113 114 115 116 117 118 119 |
{ struct module *mod; for (mod = modules; mod; mod = mod->next) if (strcmp(mod->name, modname) == 0) break; return mod; } |
d4ef1c30e modpost: minor cl... |
120 |
static struct module *new_module(const char *modname) |
1da177e4c Linux-2.6.12-rc2 |
121 122 |
{ struct module *mod; |
d4ef1c30e modpost: minor cl... |
123 |
char *p; |
62070fa42 kbuild: kill trai... |
124 |
|
1da177e4c Linux-2.6.12-rc2 |
125 126 127 128 129 |
mod = NOFAIL(malloc(sizeof(*mod))); memset(mod, 0, sizeof(*mod)); p = NOFAIL(strdup(modname)); /* strip trailing .o */ |
d4ef1c30e modpost: minor cl... |
130 131 132 133 |
if (strends(p, ".o")) { p[strlen(p) - 2] = '\0'; mod->is_dot_o = 1; } |
1da177e4c Linux-2.6.12-rc2 |
134 135 136 |
/* add to list */ mod->name = p; |
b817f6fef kbuild: check lic... |
137 |
mod->gpl_compatible = -1; |
1da177e4c Linux-2.6.12-rc2 |
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
mod->next = modules; modules = mod; return mod; } /* A hash of all exported symbols, * struct symbol is also used for lists of unresolved symbols */ #define SYMBOL_HASH_SIZE 1024 struct symbol { struct symbol *next; struct module *module; unsigned int crc; int crc_valid; unsigned int weak:1; |
040fcc819 kbuild: improved ... |
155 156 157 |
unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ unsigned int kernel:1; /* 1 if symbol is from kernel * (only for external modules) **/ |
b6568b1a1 modpost: fix bogu... |
158 |
unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */ |
bd5cbcedf kbuild: export-ty... |
159 |
enum export export; /* Type of export */ |
1da177e4c Linux-2.6.12-rc2 |
160 161 162 163 164 165 166 167 168 169 170 171 |
char name[0]; }; static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; /* This is based on the hash agorithm from gdbm, via tdb */ static inline unsigned int tdb_hash(const char *name) { unsigned value; /* Used to compute the hash value. */ unsigned i; /* Used to cycle through random values. */ /* Set the initial value from the key size. */ |
df578e7d8 kbuild: clean up ... |
172 |
for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) |
1da177e4c Linux-2.6.12-rc2 |
173 174 175 176 |
value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); return (1103515243 * value + 12345); } |
5c3ead8c7 kbuild: apply Cod... |
177 178 179 180 181 182 |
/** * Allocate a new symbols for use in the hash of exported symbols or * the list of unresolved symbols per module **/ static struct symbol *alloc_symbol(const char *name, unsigned int weak, struct symbol *next) |
1da177e4c Linux-2.6.12-rc2 |
183 184 185 186 187 188 189 190 191 192 193 |
{ struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); memset(s, 0, sizeof(*s)); strcpy(s->name, name); s->weak = weak; s->next = next; return s; } /* For the hash of exported symbols */ |
bd5cbcedf kbuild: export-ty... |
194 195 |
static struct symbol *new_symbol(const char *name, struct module *module, enum export export) |
1da177e4c Linux-2.6.12-rc2 |
196 197 198 199 200 201 202 |
{ unsigned int hash; struct symbol *new; hash = tdb_hash(name) % SYMBOL_HASH_SIZE; new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); new->module = module; |
bd5cbcedf kbuild: export-ty... |
203 |
new->export = export; |
040fcc819 kbuild: improved ... |
204 |
return new; |
1da177e4c Linux-2.6.12-rc2 |
205 |
} |
5c3ead8c7 kbuild: apply Cod... |
206 |
static struct symbol *find_symbol(const char *name) |
1da177e4c Linux-2.6.12-rc2 |
207 208 209 210 211 212 |
{ struct symbol *s; /* For our purposes, .foo matches foo. PPC64 needs this. */ if (name[0] == '.') name++; |
df578e7d8 kbuild: clean up ... |
213 |
for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) { |
1da177e4c Linux-2.6.12-rc2 |
214 215 216 217 218 |
if (strcmp(s->name, name) == 0) return s; } return NULL; } |
bd5cbcedf kbuild: export-ty... |
219 220 221 222 223 |
static struct { const char *str; enum export export; } export_list[] = { { .str = "EXPORT_SYMBOL", .export = export_plain }, |
c96fca213 kbuild: warn when... |
224 |
{ .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, |
bd5cbcedf kbuild: export-ty... |
225 |
{ .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, |
c96fca213 kbuild: warn when... |
226 |
{ .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, |
bd5cbcedf kbuild: export-ty... |
227 228 229 230 231 232 233 234 235 |
{ .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, { .str = "(unknown)", .export = export_unknown }, }; static const char *export_str(enum export ex) { return export_list[ex].str; } |
df578e7d8 kbuild: clean up ... |
236 |
static enum export export_no(const char *s) |
bd5cbcedf kbuild: export-ty... |
237 238 |
{ int i; |
df578e7d8 kbuild: clean up ... |
239 |
|
534b89a9f kbuild: fix segv ... |
240 241 |
if (!s) return export_unknown; |
bd5cbcedf kbuild: export-ty... |
242 243 244 245 246 247 |
for (i = 0; export_list[i].export != export_unknown; i++) { if (strcmp(export_list[i].str, s) == 0) return export_list[i].export; } return export_unknown; } |
62a263561 modpost: Fix modp... |
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
static const char *sec_name(struct elf_info *elf, int secindex); #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) static enum export export_from_secname(struct elf_info *elf, unsigned int sec) { const char *secname = sec_name(elf, sec); if (strstarts(secname, "___ksymtab+")) return export_plain; else if (strstarts(secname, "___ksymtab_unused+")) return export_unused; else if (strstarts(secname, "___ksymtab_gpl+")) return export_gpl; else if (strstarts(secname, "___ksymtab_unused_gpl+")) return export_unused_gpl; else if (strstarts(secname, "___ksymtab_gpl_future+")) return export_gpl_future; else return export_unknown; } |
1ce53adf1 modpost: support ... |
269 |
static enum export export_from_sec(struct elf_info *elf, unsigned int sec) |
bd5cbcedf kbuild: export-ty... |
270 271 272 |
{ if (sec == elf->export_sec) return export_plain; |
c96fca213 kbuild: warn when... |
273 274 |
else if (sec == elf->export_unused_sec) return export_unused; |
bd5cbcedf kbuild: export-ty... |
275 276 |
else if (sec == elf->export_gpl_sec) return export_gpl; |
c96fca213 kbuild: warn when... |
277 278 |
else if (sec == elf->export_unused_gpl_sec) return export_unused_gpl; |
bd5cbcedf kbuild: export-ty... |
279 280 281 282 283 |
else if (sec == elf->export_gpl_future_sec) return export_gpl_future; else return export_unknown; } |
5c3ead8c7 kbuild: apply Cod... |
284 285 286 287 |
/** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC **/ |
bd5cbcedf kbuild: export-ty... |
288 289 |
static struct symbol *sym_add_exported(const char *name, struct module *mod, enum export export) |
1da177e4c Linux-2.6.12-rc2 |
290 291 292 293 |
{ struct symbol *s = find_symbol(name); if (!s) { |
bd5cbcedf kbuild: export-ty... |
294 |
s = new_symbol(name, mod, export); |
8e70c4588 kbuild: warn abou... |
295 296 |
} else { if (!s->preloaded) { |
7b75b13cd kbuild: when warn... |
297 |
warn("%s: '%s' exported twice. Previous export " |
8e70c4588 kbuild: warn abou... |
298 299 300 301 |
"was in %s%s ", mod->name, name, s->module->name, is_vmlinux(s->module->name) ?"":".ko"); |
4b21960f9 kbuild: modpost p... |
302 303 304 |
} else { /* In case Modules.symvers was out of date */ s->module = mod; |
8e70c4588 kbuild: warn abou... |
305 |
} |
1da177e4c Linux-2.6.12-rc2 |
306 |
} |
8e70c4588 kbuild: warn abou... |
307 |
s->preloaded = 0; |
040fcc819 kbuild: improved ... |
308 309 |
s->vmlinux = is_vmlinux(mod->name); s->kernel = 0; |
bd5cbcedf kbuild: export-ty... |
310 |
s->export = export; |
040fcc819 kbuild: improved ... |
311 312 313 314 |
return s; } static void sym_update_crc(const char *name, struct module *mod, |
bd5cbcedf kbuild: export-ty... |
315 |
unsigned int crc, enum export export) |
040fcc819 kbuild: improved ... |
316 317 |
{ struct symbol *s = find_symbol(name); |
b6568b1a1 modpost: fix bogu... |
318 |
if (!s) { |
bd5cbcedf kbuild: export-ty... |
319 |
s = new_symbol(name, mod, export); |
b6568b1a1 modpost: fix bogu... |
320 321 322 |
/* Don't complain when we find it later. */ s->preloaded = 1; } |
040fcc819 kbuild: improved ... |
323 324 |
s->crc = crc; s->crc_valid = 1; |
1da177e4c Linux-2.6.12-rc2 |
325 |
} |
5c3ead8c7 kbuild: apply Cod... |
326 |
void *grab_file(const char *filename, unsigned long *size) |
1da177e4c Linux-2.6.12-rc2 |
327 328 |
{ struct stat st; |
eb3d5cc67 modpost: Stop gra... |
329 |
void *map = MAP_FAILED; |
1da177e4c Linux-2.6.12-rc2 |
330 331 332 |
int fd; fd = open(filename, O_RDONLY); |
eb3d5cc67 modpost: Stop gra... |
333 |
if (fd < 0) |
1da177e4c Linux-2.6.12-rc2 |
334 |
return NULL; |
eb3d5cc67 modpost: Stop gra... |
335 336 |
if (fstat(fd, &st)) goto failed; |
1da177e4c Linux-2.6.12-rc2 |
337 338 339 |
*size = st.st_size; map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); |
1da177e4c Linux-2.6.12-rc2 |
340 |
|
eb3d5cc67 modpost: Stop gra... |
341 342 |
failed: close(fd); |
1da177e4c Linux-2.6.12-rc2 |
343 344 345 346 |
if (map == MAP_FAILED) return NULL; return map; } |
5c3ead8c7 kbuild: apply Cod... |
347 348 349 350 351 |
/** * Return a copy of the next line in a mmap'ed file. * spaces in the beginning of the line is trimmed away. * Return a pointer to a static buffer. **/ |
df578e7d8 kbuild: clean up ... |
352 |
char *get_next_line(unsigned long *pos, void *file, unsigned long size) |
1da177e4c Linux-2.6.12-rc2 |
353 354 355 356 357 358 |
{ static char line[4096]; int skip = 1; size_t len = 0; signed char *p = (signed char *)file + *pos; char *s = line; |
df578e7d8 kbuild: clean up ... |
359 |
for (; *pos < size ; (*pos)++) { |
1da177e4c Linux-2.6.12-rc2 |
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
if (skip && isspace(*p)) { p++; continue; } skip = 0; if (*p != ' ' && (*pos < size)) { len++; *s++ = *p++; if (len > 4095) break; /* Too long, stop */ } else { /* End of string */ *s = '\0'; return line; } } /* End of buffer */ return NULL; } |
5c3ead8c7 kbuild: apply Cod... |
380 |
void release_file(void *file, unsigned long size) |
1da177e4c Linux-2.6.12-rc2 |
381 382 383 |
{ munmap(file, size); } |
85bd2fddd kbuild: fix secti... |
384 |
static int parse_elf(struct elf_info *info, const char *filename) |
1da177e4c Linux-2.6.12-rc2 |
385 386 |
{ unsigned int i; |
85bd2fddd kbuild: fix secti... |
387 |
Elf_Ehdr *hdr; |
1da177e4c Linux-2.6.12-rc2 |
388 389 |
Elf_Shdr *sechdrs; Elf_Sym *sym; |
1ce53adf1 modpost: support ... |
390 391 |
const char *secstrings; unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U; |
1da177e4c Linux-2.6.12-rc2 |
392 393 394 |
hdr = grab_file(filename, &info->size); if (!hdr) { |
eed380f3f modpost: Optional... |
395 396 397 398 399 400 |
if (ignore_missing_files) { fprintf(stderr, "%s: %s (ignored) ", filename, strerror(errno)); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
401 |
perror(filename); |
6803dc0ea kbuild: replace a... |
402 |
exit(1); |
1da177e4c Linux-2.6.12-rc2 |
403 404 |
} info->hdr = hdr; |
85bd2fddd kbuild: fix secti... |
405 406 407 408 409 410 411 412 413 414 415 416 |
if (info->size < sizeof(*hdr)) { /* file too small, assume this is an empty .o file */ return 0; } /* Is this a valid ELF file? */ if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || (hdr->e_ident[EI_MAG1] != ELFMAG1) || (hdr->e_ident[EI_MAG2] != ELFMAG2) || (hdr->e_ident[EI_MAG3] != ELFMAG3)) { /* Not an ELF file - silently ignore it */ return 0; } |
1da177e4c Linux-2.6.12-rc2 |
417 |
/* Fix endianness in ELF header */ |
7d875a028 kbuild, modpost: ... |
418 419 420 421 422 423 424 425 426 427 428 429 430 |
hdr->e_type = TO_NATIVE(hdr->e_type); hdr->e_machine = TO_NATIVE(hdr->e_machine); hdr->e_version = TO_NATIVE(hdr->e_version); hdr->e_entry = TO_NATIVE(hdr->e_entry); hdr->e_phoff = TO_NATIVE(hdr->e_phoff); hdr->e_shoff = TO_NATIVE(hdr->e_shoff); hdr->e_flags = TO_NATIVE(hdr->e_flags); hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize); hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize); hdr->e_phnum = TO_NATIVE(hdr->e_phnum); hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize); hdr->e_shnum = TO_NATIVE(hdr->e_shnum); hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); |
1da177e4c Linux-2.6.12-rc2 |
431 432 |
sechdrs = (void *)hdr + hdr->e_shoff; info->sechdrs = sechdrs; |
a83710e58 kbuild: fix segfa... |
433 434 |
/* Check if file offset is correct */ if (hdr->e_shoff > info->size) { |
df578e7d8 kbuild: clean up ... |
435 436 437 438 |
fatal("section header offset=%lu in file '%s' is bigger than " "filesize=%lu ", (unsigned long)hdr->e_shoff, filename, info->size); |
a83710e58 kbuild: fix segfa... |
439 440 |
return 0; } |
6845756b2 modpost: Update 6... |
441 |
if (hdr->e_shnum == SHN_UNDEF) { |
1ce53adf1 modpost: support ... |
442 443 444 |
/* * There are more than 64k sections, * read count from .sh_size. |
1ce53adf1 modpost: support ... |
445 446 447 448 449 450 451 |
*/ info->num_sections = TO_NATIVE(sechdrs[0].sh_size); } else { info->num_sections = hdr->e_shnum; } if (hdr->e_shstrndx == SHN_XINDEX) { |
6845756b2 modpost: Update 6... |
452 |
info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link); |
1ce53adf1 modpost: support ... |
453 454 455 456 |
} else { info->secindex_strings = hdr->e_shstrndx; } |
1da177e4c Linux-2.6.12-rc2 |
457 |
/* Fix endianness in section headers */ |
1ce53adf1 modpost: support ... |
458 |
for (i = 0; i < info->num_sections; i++) { |
7d875a028 kbuild, modpost: ... |
459 460 461 462 463 464 465 466 467 468 |
sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign); sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); |
1da177e4c Linux-2.6.12-rc2 |
469 470 |
} /* Find symbol table. */ |
1ce53adf1 modpost: support ... |
471 472 |
secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset; for (i = 1; i < info->num_sections; i++) { |
bd5cbcedf kbuild: export-ty... |
473 |
const char *secname; |
56fc82c53 modpost: NOBITS s... |
474 |
int nobits = sechdrs[i].sh_type == SHT_NOBITS; |
1da177e4c Linux-2.6.12-rc2 |
475 |
|
56fc82c53 modpost: NOBITS s... |
476 |
if (!nobits && sechdrs[i].sh_offset > info->size) { |
df578e7d8 kbuild: clean up ... |
477 478 479 480 481 |
fatal("%s is truncated. sechdrs[i].sh_offset=%lu > " "sizeof(*hrd)=%zu ", filename, (unsigned long)sechdrs[i].sh_offset, sizeof(*hdr)); |
85bd2fddd kbuild: fix secti... |
482 483 |
return 0; } |
bd5cbcedf kbuild: export-ty... |
484 485 |
secname = secstrings + sechdrs[i].sh_name; if (strcmp(secname, ".modinfo") == 0) { |
56fc82c53 modpost: NOBITS s... |
486 487 488 |
if (nobits) fatal("%s has NOBITS .modinfo ", filename); |
1da177e4c Linux-2.6.12-rc2 |
489 490 |
info->modinfo = (void *)hdr + sechdrs[i].sh_offset; info->modinfo_len = sechdrs[i].sh_size; |
bd5cbcedf kbuild: export-ty... |
491 492 |
} else if (strcmp(secname, "__ksymtab") == 0) info->export_sec = i; |
c96fca213 kbuild: warn when... |
493 494 |
else if (strcmp(secname, "__ksymtab_unused") == 0) info->export_unused_sec = i; |
bd5cbcedf kbuild: export-ty... |
495 496 |
else if (strcmp(secname, "__ksymtab_gpl") == 0) info->export_gpl_sec = i; |
c96fca213 kbuild: warn when... |
497 498 |
else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) info->export_unused_gpl_sec = i; |
bd5cbcedf kbuild: export-ty... |
499 500 |
else if (strcmp(secname, "__ksymtab_gpl_future") == 0) info->export_gpl_future_sec = i; |
1ce53adf1 modpost: support ... |
501 502 503 504 505 506 507 |
if (sechdrs[i].sh_type == SHT_SYMTAB) { unsigned int sh_link_idx; symtab_idx = i; info->symtab_start = (void *)hdr + sechdrs[i].sh_offset; info->symtab_stop = (void *)hdr + sechdrs[i].sh_offset + sechdrs[i].sh_size; |
6845756b2 modpost: Update 6... |
508 |
sh_link_idx = sechdrs[i].sh_link; |
1ce53adf1 modpost: support ... |
509 510 511 |
info->strtab = (void *)hdr + sechdrs[sh_link_idx].sh_offset; } |
1da177e4c Linux-2.6.12-rc2 |
512 |
|
1ce53adf1 modpost: support ... |
513 514 515 516 517 518 519 520 |
/* 32bit section no. table? ("more than 64k sections") */ if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) { symtab_shndx_idx = i; info->symtab_shndx_start = (void *)hdr + sechdrs[i].sh_offset; info->symtab_shndx_stop = (void *)hdr + sechdrs[i].sh_offset + sechdrs[i].sh_size; } |
1da177e4c Linux-2.6.12-rc2 |
521 |
} |
df578e7d8 kbuild: clean up ... |
522 |
if (!info->symtab_start) |
cb80514d9 kbuild: use warn(... |
523 524 |
fatal("%s has no symtab? ", filename); |
df578e7d8 kbuild: clean up ... |
525 |
|
1da177e4c Linux-2.6.12-rc2 |
526 527 528 529 530 531 532 |
/* Fix endianness in symbols */ for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { sym->st_shndx = TO_NATIVE(sym->st_shndx); sym->st_name = TO_NATIVE(sym->st_name); sym->st_value = TO_NATIVE(sym->st_value); sym->st_size = TO_NATIVE(sym->st_size); } |
1ce53adf1 modpost: support ... |
533 534 535 |
if (symtab_shndx_idx != ~0U) { Elf32_Word *p; |
6845756b2 modpost: Update 6... |
536 |
if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link) |
1ce53adf1 modpost: support ... |
537 538 |
fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u ", |
6845756b2 modpost: Update 6... |
539 |
filename, sechdrs[symtab_shndx_idx].sh_link, |
1ce53adf1 modpost: support ... |
540 541 542 543 544 545 |
symtab_idx); /* Fix endianness */ for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; p++) *p = TO_NATIVE(*p); } |
85bd2fddd kbuild: fix secti... |
546 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
547 |
} |
5c3ead8c7 kbuild: apply Cod... |
548 |
static void parse_elf_finish(struct elf_info *info) |
1da177e4c Linux-2.6.12-rc2 |
549 550 551 |
{ release_file(info->hdr, info->size); } |
4d7365d66 kbuild: ignore po... |
552 553 554 |
static int ignore_undef_symbol(struct elf_info *info, const char *symname) { /* ignore __this_module, it will be resolved shortly */ |
b92021b09 CONFIG_SYMBOL_PRE... |
555 |
if (strcmp(symname, VMLINUX_SYMBOL_STR(__this_module)) == 0) |
4d7365d66 kbuild: ignore po... |
556 557 558 559 560 561 562 563 564 |
return 1; /* ignore global offset table */ if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) return 1; if (info->hdr->e_machine == EM_PPC) /* Special register function linked on all modules during final link of .ko */ if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 || strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 || strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 || |
8fe9c93e7 powerpc: Add vr s... |
565 566 567 |
strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0 || strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0) |
4d7365d66 kbuild: ignore po... |
568 |
return 1; |
7fca5dc8a powerpc: Fix modu... |
569 570 571 |
if (info->hdr->e_machine == EM_PPC64) /* Special register function linked on all modules during final link of .ko */ if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 || |
8fe9c93e7 powerpc: Add vr s... |
572 573 574 |
strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 || strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0) |
7fca5dc8a powerpc: Fix modu... |
575 |
return 1; |
4d7365d66 kbuild: ignore po... |
576 577 578 |
/* Do not ignore this symbol */ return 0; } |
b92021b09 CONFIG_SYMBOL_PRE... |
579 580 |
#define CRC_PFX VMLINUX_SYMBOL_STR(__crc_) #define KSYMTAB_PFX VMLINUX_SYMBOL_STR(__ksymtab_) |
1da177e4c Linux-2.6.12-rc2 |
581 |
|
5c3ead8c7 kbuild: apply Cod... |
582 583 |
static void handle_modversions(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname) |
1da177e4c Linux-2.6.12-rc2 |
584 585 |
{ unsigned int crc; |
62a263561 modpost: Fix modp... |
586 |
enum export export; |
258f74263 modpost: Fix modp... |
587 588 |
if ((!is_vmlinux(mod->name) || mod->is_dot_o) && strncmp(symname, "__ksymtab", 9) == 0) |
62a263561 modpost: Fix modp... |
589 590 591 |
export = export_from_secname(info, get_secindex(info, sym)); else export = export_from_sec(info, get_secindex(info, sym)); |
1da177e4c Linux-2.6.12-rc2 |
592 |
|
b5064654c scripts/mod/modpo... |
593 594 595 596 597 598 |
/* CRC'd symbol */ if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { crc = (unsigned int) sym->st_value; sym_update_crc(symname + strlen(CRC_PFX), mod, crc, export); } |
1da177e4c Linux-2.6.12-rc2 |
599 600 |
switch (sym->st_shndx) { case SHN_COMMON: |
ef178f923 Kbuild, lto: Hand... |
601 602 603 604 605 |
if (!strncmp(symname, "__gnu_lto_", sizeof("__gnu_lto_")-1)) { /* Should warn here, but modpost runs before the linker */ } else warn("\"%s\" [%s] is COMMON symbol ", symname, mod->name); |
1da177e4c Linux-2.6.12-rc2 |
606 |
break; |
1da177e4c Linux-2.6.12-rc2 |
607 608 609 610 611 |
case SHN_UNDEF: /* undefined symbol */ if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && ELF_ST_BIND(sym->st_info) != STB_WEAK) break; |
4d7365d66 kbuild: ignore po... |
612 |
if (ignore_undef_symbol(info, symname)) |
1da177e4c Linux-2.6.12-rc2 |
613 |
break; |
8d5290149 [SPARC]: Deal wit... |
614 615 616 617 618 619 |
/* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */ #if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER) /* add compatibility with older glibc */ #ifndef STT_SPARC_REGISTER #define STT_SPARC_REGISTER STT_REGISTER #endif |
1da177e4c Linux-2.6.12-rc2 |
620 621 622 |
if (info->hdr->e_machine == EM_SPARC || info->hdr->e_machine == EM_SPARCV9) { /* Ignore register directives. */ |
8d5290149 [SPARC]: Deal wit... |
623 |
if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) |
1da177e4c Linux-2.6.12-rc2 |
624 |
break; |
62070fa42 kbuild: kill trai... |
625 626 627 628 629 630 |
if (symname[0] == '.') { char *munged = strdup(symname); munged[0] = '_'; munged[1] = toupper(munged[1]); symname = munged; } |
1da177e4c Linux-2.6.12-rc2 |
631 632 |
} #endif |
62070fa42 kbuild: kill trai... |
633 |
|
b92021b09 CONFIG_SYMBOL_PRE... |
634 635 636 637 638 639 640 641 642 |
#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX if (symname[0] != '_') break; else symname++; #endif mod->unres = alloc_symbol(symname, ELF_ST_BIND(sym->st_info) == STB_WEAK, mod->unres); |
1da177e4c Linux-2.6.12-rc2 |
643 644 645 |
break; default: /* All exported symbols */ |
8d99513c1 modpost: fix segf... |
646 |
if (strncmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { |
bd5cbcedf kbuild: export-ty... |
647 648 |
sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, export); |
1da177e4c Linux-2.6.12-rc2 |
649 |
} |
b92021b09 CONFIG_SYMBOL_PRE... |
650 |
if (strcmp(symname, VMLINUX_SYMBOL_STR(init_module)) == 0) |
1da177e4c Linux-2.6.12-rc2 |
651 |
mod->has_init = 1; |
b92021b09 CONFIG_SYMBOL_PRE... |
652 |
if (strcmp(symname, VMLINUX_SYMBOL_STR(cleanup_module)) == 0) |
1da177e4c Linux-2.6.12-rc2 |
653 654 655 656 |
mod->has_cleanup = 1; break; } } |
5c3ead8c7 kbuild: apply Cod... |
657 658 659 |
/** * Parse tag=value strings from .modinfo section **/ |
1da177e4c Linux-2.6.12-rc2 |
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 |
static char *next_string(char *string, unsigned long *secsize) { /* Skip non-zero chars */ while (string[0]) { string++; if ((*secsize)-- <= 1) return NULL; } /* Skip any zero padding. */ while (!string[0]) { string++; if ((*secsize)-- <= 1) return NULL; } return string; } |
b817f6fef kbuild: check lic... |
677 678 |
static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len, const char *tag, char *info) |
1da177e4c Linux-2.6.12-rc2 |
679 680 681 682 |
{ char *p; unsigned int taglen = strlen(tag); unsigned long size = modinfo_len; |
b817f6fef kbuild: check lic... |
683 684 685 686 |
if (info) { size -= info - (char *)modinfo; modinfo = next_string(info, &size); } |
1da177e4c Linux-2.6.12-rc2 |
687 688 689 690 691 692 |
for (p = modinfo; p; p = next_string(p, &size)) { if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') return p + taglen + 1; } return NULL; } |
b817f6fef kbuild: check lic... |
693 694 695 696 697 698 |
static char *get_modinfo(void *modinfo, unsigned long modinfo_len, const char *tag) { return get_next_modinfo(modinfo, modinfo_len, tag, NULL); } |
93684d3b8 kbuild: include s... |
699 |
/** |
4c8fbca58 kbuild: whitelist... |
700 701 702 703 704 |
* Test if string s ends in string sub * return 0 if match **/ static int strrcmp(const char *s, const char *sub) { |
df578e7d8 kbuild: clean up ... |
705 |
int slen, sublen; |
62070fa42 kbuild: kill trai... |
706 |
|
4c8fbca58 kbuild: whitelist... |
707 708 |
if (!s || !sub) return 1; |
62070fa42 kbuild: kill trai... |
709 |
|
4c8fbca58 kbuild: whitelist... |
710 |
slen = strlen(s); |
df578e7d8 kbuild: clean up ... |
711 |
sublen = strlen(sub); |
62070fa42 kbuild: kill trai... |
712 |
|
4c8fbca58 kbuild: whitelist... |
713 714 |
if ((slen == 0) || (sublen == 0)) return 1; |
df578e7d8 kbuild: clean up ... |
715 716 |
if (sublen > slen) return 1; |
4c8fbca58 kbuild: whitelist... |
717 |
|
df578e7d8 kbuild: clean up ... |
718 |
return memcmp(s + slen - sublen, sub, sublen); |
4c8fbca58 kbuild: whitelist... |
719 |
} |
ff13f9269 kbuild: introduce... |
720 721 |
static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) { |
58fb0d4f2 kbuild: simplifie... |
722 723 724 |
if (sym) return elf->strtab + sym->st_name; else |
f666751a0 kbuild/modpost: i... |
725 |
return "(unknown)"; |
ff13f9269 kbuild: introduce... |
726 |
} |
1ce53adf1 modpost: support ... |
727 |
static const char *sec_name(struct elf_info *elf, int secindex) |
ff13f9269 kbuild: introduce... |
728 729 730 |
{ Elf_Shdr *sechdrs = elf->sechdrs; return (void *)elf->hdr + |
1ce53adf1 modpost: support ... |
731 732 |
elf->sechdrs[elf->secindex_strings].sh_offset + sechdrs[secindex].sh_name; |
ff13f9269 kbuild: introduce... |
733 734 735 736 737 |
} static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) { return (void *)elf->hdr + |
1ce53adf1 modpost: support ... |
738 739 |
elf->sechdrs[elf->secindex_strings].sh_offset + sechdr->sh_name; |
ff13f9269 kbuild: introduce... |
740 |
} |
10668220a kbuild: introduce... |
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 |
/* if sym is empty or point to a string * like ".[0-9]+" then return 1. * This is the optional prefix added by ld to some sections */ static int number_prefix(const char *sym) { if (*sym++ == '\0') return 1; if (*sym != '.') return 0; do { char c = *sym++; if (c < '0' || c > '9') return 0; } while (*sym); return 1; } /* The pattern is an array of simple patterns. * "foo" will match an exact string equal to "foo" |
6c5bd235b kbuild: check sec... |
761 |
* "*foo" will match a string that ends with "foo" |
10668220a kbuild: introduce... |
762 763 764 765 766 767 |
* "foo*" will match a string that begins with "foo" * "foo$" will match a string equal to "foo" or "foo.1" * where the '1' can be any number including several digits. * The $ syntax is for sections where ld append a dot number * to make section name unique. */ |
5c7251384 Fix all -Wmissing... |
768 |
static int match(const char *sym, const char * const pat[]) |
10668220a kbuild: introduce... |
769 770 771 772 773 |
{ const char *p; while (*pat) { p = *pat++; const char *endp = p + strlen(p) - 1; |
6c5bd235b kbuild: check sec... |
774 775 776 777 778 |
/* "*foo" */ if (*p == '*') { if (strrcmp(sym, p + 1) == 0) return 1; } |
10668220a kbuild: introduce... |
779 |
/* "foo*" */ |
6c5bd235b kbuild: check sec... |
780 |
else if (*endp == '*') { |
10668220a kbuild: introduce... |
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 |
if (strncmp(sym, p, strlen(p) - 1) == 0) return 1; } /* "foo$" */ else if (*endp == '$') { if (strncmp(sym, p, strlen(p) - 1) == 0) { if (number_prefix(sym + strlen(p) - 1)) return 1; } } /* no wildcards */ else { if (strcmp(p, sym) == 0) return 1; } } /* no match */ return 0; } |
10668220a kbuild: introduce... |
800 801 |
/* sections that we do not want to do full section mismatch check on */ static const char *section_white_list[] = |
4391ed6aa kbuild, modpost: ... |
802 803 804 |
{ ".comment*", ".debug*", |
4d10c223b scripts/mod/modpo... |
805 |
".cranges", /* sh64 */ |
1121584f5 modpost: Put .zde... |
806 |
".zdebug*", /* Compressed debug sections. */ |
019fca84e MN10300: Permit .... |
807 |
".GCC-command-line", /* mn10300 */ |
76b27645a modpost: Permit .... |
808 |
".GCC.command.line", /* record-gcc-switches, non mn10300 */ |
4391ed6aa kbuild, modpost: ... |
809 810 811 812 813 814 |
".mdebug*", /* alpha, score, mips etc. */ ".pdr", /* alpha, score, mips etc. */ ".stab*", ".note*", ".got*", ".toc*", |
af42e970b modpost: fix modp... |
815 816 |
".xt.prop", /* xtensa */ ".xt.lit", /* xtensa */ |
f2e207f32 modpost: Ignore A... |
817 818 |
".arcextmap*", /* arc */ ".gnu.linkonce.arcext*", /* arc : modules */ |
ef178f923 Kbuild, lto: Hand... |
819 |
".gnu.lto*", |
4391ed6aa kbuild, modpost: ... |
820 821 |
NULL }; |
10668220a kbuild: introduce... |
822 |
|
e241a6303 kbuild: warn abou... |
823 |
/* |
b614a697d kbuild, modpost: ... |
824 |
* This is used to find sections missing the SHF_ALLOC flag. |
e241a6303 kbuild: warn abou... |
825 |
* The cause of this is often a section specified in assembler |
b614a697d kbuild, modpost: ... |
826 |
* without "ax" / "aw". |
e241a6303 kbuild: warn abou... |
827 |
*/ |
b614a697d kbuild, modpost: ... |
828 829 |
static void check_section(const char *modname, struct elf_info *elf, Elf_Shdr *sechdr) |
e241a6303 kbuild: warn abou... |
830 |
{ |
b614a697d kbuild, modpost: ... |
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 |
const char *sec = sech_name(elf, sechdr); if (sechdr->sh_type == SHT_PROGBITS && !(sechdr->sh_flags & SHF_ALLOC) && !match(sec, section_white_list)) { warn("%s (%s): unexpected non-allocatable section. " "Did you forget to use \"ax\"/\"aw\" in a .S file? " "Note that for example <linux/init.h> contains " "section definitions for use in .S files. ", modname, sec); |
e241a6303 kbuild: warn abou... |
846 |
} |
e241a6303 kbuild: warn abou... |
847 |
} |
eb8f68904 Use separate sect... |
848 |
#define ALL_INIT_DATA_SECTIONS \ |
e24f66288 modpost: remove a... |
849 850 |
".init.setup$", ".init.rodata$", ".meminit.rodata$", \ ".init.data$", ".meminit.data$" |
eb8f68904 Use separate sect... |
851 |
#define ALL_EXIT_DATA_SECTIONS \ |
e24f66288 modpost: remove a... |
852 |
".exit.data$", ".memexit.data$" |
10668220a kbuild: introduce... |
853 |
|
eb8f68904 Use separate sect... |
854 |
#define ALL_INIT_TEXT_SECTIONS \ |
e24f66288 modpost: remove a... |
855 |
".init.text$", ".meminit.text$" |
eb8f68904 Use separate sect... |
856 |
#define ALL_EXIT_TEXT_SECTIONS \ |
e24f66288 modpost: remove a... |
857 |
".exit.text$", ".memexit.text$" |
10668220a kbuild: introduce... |
858 |
|
bb15d8db7 scripts/modpost: ... |
859 860 861 862 |
#define ALL_PCI_INIT_SECTIONS \ ".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \ ".pci_fixup_enable$", ".pci_fixup_resume$", \ ".pci_fixup_resume_early$", ".pci_fixup_suspend$" |
e24f66288 modpost: remove a... |
863 864 |
#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS #define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS |
4a31a229f modpost: define A... |
865 866 867 |
#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS |
10668220a kbuild: introduce... |
868 |
|
6c5bd235b kbuild: check sec... |
869 |
#define DATA_SECTIONS ".data$", ".data.rel$" |
06df44ee4 modpost.c: Add .t... |
870 |
#define TEXT_SECTIONS ".text$", ".text.unlikely$" |
10668220a kbuild: introduce... |
871 |
|
fd6c3a8dc initconst adjustm... |
872 |
#define INIT_SECTIONS ".init.*" |
fd6c3a8dc initconst adjustm... |
873 |
#define MEM_INIT_SECTIONS ".meminit.*" |
eb8f68904 Use separate sect... |
874 |
|
fd6c3a8dc initconst adjustm... |
875 |
#define EXIT_SECTIONS ".exit.*" |
fd6c3a8dc initconst adjustm... |
876 |
#define MEM_EXIT_SECTIONS ".memexit.*" |
eb8f68904 Use separate sect... |
877 |
|
6c5bd235b kbuild: check sec... |
878 |
/* init data sections */ |
eb8f68904 Use separate sect... |
879 |
static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL }; |
6c5bd235b kbuild: check sec... |
880 881 |
/* all init sections */ |
eb8f68904 Use separate sect... |
882 |
static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL }; |
6c5bd235b kbuild: check sec... |
883 884 885 |
/* All init and exit sections (code + data) */ static const char *init_exit_sections[] = |
eb8f68904 Use separate sect... |
886 |
{ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; |
6c5bd235b kbuild: check sec... |
887 888 889 |
/* data section */ static const char *data_sections[] = { DATA_SECTIONS, NULL }; |
6c5bd235b kbuild: check sec... |
890 891 |
/* symbols in .data that may refer to init/exit sections */ |
af92a82d0 modpost: make sym... |
892 893 894 895 896 897 898 899 900 |
#define DEFAULT_SYMBOL_WHITE_LIST \ "*driver", \ "*_template", /* scsi uses *_template a lot */ \ "*_timer", /* arm uses ops structures named _timer a lot */ \ "*_sht", /* scsi also used *_sht to some extent */ \ "*_ops", \ "*_probe", \ "*_probe_one", \ "*_console" |
6c5bd235b kbuild: check sec... |
901 902 903 904 |
static const char *head_sections[] = { ".head.text*", NULL }; static const char *linker_symbols[] = { "__init_begin", "_sinittext", "_einittext", NULL }; |
588ccd732 kbuild: add verbo... |
905 |
enum mismatch { |
bbd3f4fb8 modpost: give mos... |
906 907 908 909 910 911 912 913 |
TEXT_TO_ANY_INIT, DATA_TO_ANY_INIT, TEXT_TO_ANY_EXIT, DATA_TO_ANY_EXIT, XXXINIT_TO_SOME_INIT, XXXEXIT_TO_SOME_EXIT, ANY_INIT_TO_ANY_EXIT, ANY_EXIT_TO_ANY_INIT, |
588ccd732 kbuild: add verbo... |
914 915 |
EXPORT_TO_INIT_EXIT, }; |
10668220a kbuild: introduce... |
916 917 918 |
struct sectioncheck { const char *fromsec[20]; const char *tosec[20]; |
588ccd732 kbuild: add verbo... |
919 |
enum mismatch mismatch; |
af92a82d0 modpost: make sym... |
920 |
const char *symbol_white_list[20]; |
10668220a kbuild: introduce... |
921 922 923 924 925 926 927 |
}; const struct sectioncheck sectioncheck[] = { /* Do not reference init/exit code/data from * normal code and data */ { |
588ccd732 kbuild: add verbo... |
928 929 |
.fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_INIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
930 |
.mismatch = TEXT_TO_ANY_INIT, |
af92a82d0 modpost: make sym... |
931 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
588ccd732 kbuild: add verbo... |
932 933 934 |
}, { .fromsec = { DATA_SECTIONS, NULL }, |
0db252452 modpost: don't al... |
935 |
.tosec = { ALL_XXXINIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
936 |
.mismatch = DATA_TO_ANY_INIT, |
af92a82d0 modpost: make sym... |
937 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
588ccd732 kbuild: add verbo... |
938 939 |
}, { |
0db252452 modpost: don't al... |
940 941 942 943 944 945 946 947 948 |
.fromsec = { DATA_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_INIT, .symbol_white_list = { "*_template", "*_timer", "*_sht", "*_ops", "*_probe", "*_probe_one", "*_console", NULL }, }, { |
588ccd732 kbuild: add verbo... |
949 950 |
.fromsec = { TEXT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
951 |
.mismatch = TEXT_TO_ANY_EXIT, |
af92a82d0 modpost: make sym... |
952 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
588ccd732 kbuild: add verbo... |
953 954 955 956 |
}, { .fromsec = { DATA_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
957 |
.mismatch = DATA_TO_ANY_EXIT, |
af92a82d0 modpost: make sym... |
958 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
eb8f68904 Use separate sect... |
959 |
}, |
e24f66288 modpost: remove a... |
960 |
/* Do not reference init code/data from meminit code/data */ |
eb8f68904 Use separate sect... |
961 |
{ |
4a31a229f modpost: define A... |
962 |
.fromsec = { ALL_XXXINIT_SECTIONS, NULL }, |
588ccd732 kbuild: add verbo... |
963 |
.tosec = { INIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
964 |
.mismatch = XXXINIT_TO_SOME_INIT, |
af92a82d0 modpost: make sym... |
965 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
eb8f68904 Use separate sect... |
966 |
}, |
e24f66288 modpost: remove a... |
967 |
/* Do not reference exit code/data from memexit code/data */ |
eb8f68904 Use separate sect... |
968 |
{ |
4a31a229f modpost: define A... |
969 |
.fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, |
588ccd732 kbuild: add verbo... |
970 |
.tosec = { EXIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
971 |
.mismatch = XXXEXIT_TO_SOME_EXIT, |
af92a82d0 modpost: make sym... |
972 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
10668220a kbuild: introduce... |
973 974 975 |
}, /* Do not use exit code/data from init code */ { |
eb8f68904 Use separate sect... |
976 977 |
.fromsec = { ALL_INIT_SECTIONS, NULL }, .tosec = { ALL_EXIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
978 |
.mismatch = ANY_INIT_TO_ANY_EXIT, |
af92a82d0 modpost: make sym... |
979 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
10668220a kbuild: introduce... |
980 981 982 |
}, /* Do not use init code/data from exit code */ { |
eb8f68904 Use separate sect... |
983 |
.fromsec = { ALL_EXIT_SECTIONS, NULL }, |
588ccd732 kbuild: add verbo... |
984 |
.tosec = { ALL_INIT_SECTIONS, NULL }, |
bbd3f4fb8 modpost: give mos... |
985 |
.mismatch = ANY_EXIT_TO_ANY_INIT, |
af92a82d0 modpost: make sym... |
986 |
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
10668220a kbuild: introduce... |
987 |
}, |
bb15d8db7 scripts/modpost: ... |
988 989 990 991 992 993 |
{ .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, .mismatch = ANY_INIT_TO_ANY_EXIT, .symbol_white_list = { NULL }, }, |
10668220a kbuild: introduce... |
994 995 996 |
/* Do not export init/exit functions or data */ { .fromsec = { "__ksymtab*", NULL }, |
fa95eb1f1 kbuild: do not wa... |
997 |
.tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, |
af92a82d0 modpost: make sym... |
998 999 |
.mismatch = EXPORT_TO_INIT_EXIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, |
10668220a kbuild: introduce... |
1000 1001 |
} }; |
0d2a636ee modpost: pass aro... |
1002 1003 |
static const struct sectioncheck *section_mismatch( const char *fromsec, const char *tosec) |
10668220a kbuild: introduce... |
1004 1005 1006 1007 1008 1009 1010 1011 |
{ int i; int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); const struct sectioncheck *check = §ioncheck[0]; for (i = 0; i < elems; i++) { if (match(fromsec, check->fromsec) && match(tosec, check->tosec)) |
0d2a636ee modpost: pass aro... |
1012 |
return check; |
10668220a kbuild: introduce... |
1013 1014 |
check++; } |
0d2a636ee modpost: pass aro... |
1015 |
return NULL; |
10668220a kbuild: introduce... |
1016 |
} |
4c8fbca58 kbuild: whitelist... |
1017 1018 |
/** * Whitelist to allow certain references to pass with no warning. |
0e0d314e6 kbuild: introduce... |
1019 |
* |
4c8fbca58 kbuild: whitelist... |
1020 1021 1022 1023 1024 1025 1026 |
* Pattern 1: * If a module parameter is declared __initdata and permissions=0 * then this is legal despite the warning generated. * We cannot see value of permissions here, so just ignore * this pattern. * The pattern is identified by: * tosec = .init.data |
9209aed07 kbuild: kill fals... |
1027 |
* fromsec = .data* |
4c8fbca58 kbuild: whitelist... |
1028 |
* atsym =__param* |
62070fa42 kbuild: kill trai... |
1029 |
* |
6a841528d param: silence .i... |
1030 1031 1032 1033 1034 1035 1036 |
* Pattern 1a: * module_param_call() ops can refer to __init set function if permissions=0 * The pattern is identified by: * tosec = .init.text * fromsec = .data* * atsym = __param_ops_* * |
4c8fbca58 kbuild: whitelist... |
1037 |
* Pattern 2: |
72ee59b57 kbuild modpost - ... |
1038 |
* Many drivers utilise a *driver container with references to |
4c8fbca58 kbuild: whitelist... |
1039 |
* add, remove, probe functions etc. |
4c8fbca58 kbuild: whitelist... |
1040 |
* the pattern is identified by: |
83cda2bb3 kbuild: be more f... |
1041 1042 |
* tosec = init or exit section * fromsec = data section |
df578e7d8 kbuild: clean up ... |
1043 1044 |
* atsym = *driver, *_template, *_sht, *_ops, *_probe, * *probe_one, *_console, *_timer |
ee6a8545a [PATCH] x86-64: M... |
1045 1046 |
* * Pattern 3: |
c993971f4 kbuild: fix comme... |
1047 |
* Whitelist all references from .head.text to any init section |
9bf8cb9b7 kbuild: fix warni... |
1048 |
* |
1d8af559f kbuild: consolida... |
1049 |
* Pattern 4: |
ee6a8545a [PATCH] x86-64: M... |
1050 1051 1052 1053 1054 1055 1056 |
* Some symbols belong to init section but still it is ok to reference * these from non-init sections as these symbols don't have any memory * allocated for them and symbol address and value are same. So even * if init section is freed, its ok to reference those symbols. * For ex. symbols marking the init section boundaries. * This pattern is identified by * refsymname = __init_begin, _sinittext, _einittext |
9bf8cb9b7 kbuild: fix warni... |
1057 |
* |
4c8fbca58 kbuild: whitelist... |
1058 |
**/ |
af92a82d0 modpost: make sym... |
1059 1060 |
static int secref_whitelist(const struct sectioncheck *mismatch, const char *fromsec, const char *fromsym, |
58fb0d4f2 kbuild: simplifie... |
1061 |
const char *tosec, const char *tosym) |
4c8fbca58 kbuild: whitelist... |
1062 |
{ |
4c8fbca58 kbuild: whitelist... |
1063 |
/* Check for pattern 1 */ |
6c5bd235b kbuild: check sec... |
1064 1065 |
if (match(tosec, init_data_sections) && match(fromsec, data_sections) && |
58fb0d4f2 kbuild: simplifie... |
1066 1067 |
(strncmp(fromsym, "__param", strlen("__param")) == 0)) return 0; |
4c8fbca58 kbuild: whitelist... |
1068 |
|
6a841528d param: silence .i... |
1069 1070 1071 1072 1073 |
/* Check for pattern 1a */ if (strcmp(tosec, ".init.text") == 0 && match(fromsec, data_sections) && (strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0)) return 0; |
4c8fbca58 kbuild: whitelist... |
1074 |
/* Check for pattern 2 */ |
6c5bd235b kbuild: check sec... |
1075 1076 |
if (match(tosec, init_exit_sections) && match(fromsec, data_sections) && |
af92a82d0 modpost: make sym... |
1077 |
match(fromsym, mismatch->symbol_white_list)) |
58fb0d4f2 kbuild: simplifie... |
1078 |
return 0; |
4c8fbca58 kbuild: whitelist... |
1079 |
|
9bf8cb9b7 kbuild: fix warni... |
1080 |
/* Check for pattern 3 */ |
6c5bd235b kbuild: check sec... |
1081 1082 |
if (match(fromsec, head_sections) && match(tosec, init_sections)) |
58fb0d4f2 kbuild: simplifie... |
1083 |
return 0; |
9bf8cb9b7 kbuild: fix warni... |
1084 |
|
1d8af559f kbuild: consolida... |
1085 |
/* Check for pattern 4 */ |
58fb0d4f2 kbuild: simplifie... |
1086 1087 |
if (match(tosym, linker_symbols)) return 0; |
9bf8cb9b7 kbuild: fix warni... |
1088 |
|
58fb0d4f2 kbuild: simplifie... |
1089 |
return 1; |
4c8fbca58 kbuild: whitelist... |
1090 1091 1092 |
} /** |
93684d3b8 kbuild: include s... |
1093 1094 1095 1096 1097 1098 |
* Find symbol based on relocation record info. * In some cases the symbol supplied is a valid symbol so * return refsym. If st_name != 0 we assume this is a valid symbol. * In other cases the symbol needs to be looked up in the symbol table * based on section and address. * **/ |
9ad21c3f3 kbuild: try harde... |
1099 |
static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, |
93684d3b8 kbuild: include s... |
1100 1101 1102 |
Elf_Sym *relsym) { Elf_Sym *sym; |
9ad21c3f3 kbuild: try harde... |
1103 1104 1105 |
Elf_Sym *near = NULL; Elf64_Sword distance = 20; Elf64_Sword d; |
1ce53adf1 modpost: support ... |
1106 |
unsigned int relsym_secindex; |
93684d3b8 kbuild: include s... |
1107 1108 1109 |
if (relsym->st_name != 0) return relsym; |
1ce53adf1 modpost: support ... |
1110 1111 |
relsym_secindex = get_secindex(elf, relsym); |
93684d3b8 kbuild: include s... |
1112 |
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
1ce53adf1 modpost: support ... |
1113 |
if (get_secindex(elf, sym) != relsym_secindex) |
93684d3b8 kbuild: include s... |
1114 |
continue; |
ae4ac1232 kbuild: make bett... |
1115 1116 |
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) continue; |
93684d3b8 kbuild: include s... |
1117 1118 |
if (sym->st_value == addr) return sym; |
9ad21c3f3 kbuild: try harde... |
1119 1120 1121 1122 1123 1124 1125 1126 |
/* Find a symbol nearby - addr are maybe negative */ d = sym->st_value - addr; if (d < 0) d = addr - sym->st_value; if (d < distance) { distance = d; near = sym; } |
93684d3b8 kbuild: include s... |
1127 |
} |
9ad21c3f3 kbuild: try harde... |
1128 1129 1130 1131 1132 |
/* We need a close match */ if (distance < 20) return near; else return NULL; |
93684d3b8 kbuild: include s... |
1133 |
} |
da68d61f8 [PATCH] remove mo... |
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 |
static inline int is_arm_mapping_symbol(const char *str) { return str[0] == '$' && strchr("atd", str[1]) && (str[2] == '\0' || str[2] == '.'); } /* * If there's no name there, ignore it; likewise, ignore it if it's * one of the magic symbols emitted used by current ARM tools. * * Otherwise if find_symbols_between() returns those symbols, they'll * fail the whitelist tests and cause lots of false alarms ... fixable * only by merging __exit and __init sections into __text, bloating * the kernel (which is especially evil on embedded platforms). */ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) { const char *name = elf->strtab + sym->st_name; if (!name || !strlen(name)) return 0; return !is_arm_mapping_symbol(name); } |
b39927cf4 kbuild: check for... |
1157 |
/* |
43c74d179 kbuild: in the se... |
1158 1159 1160 1161 |
* Find symbols before or equal addr and after addr - in the section sec. * If we find two symbols with equal offset prefer one with a valid name. * The ELF format may have a better way to detect what type of symbol * it is, but this works for now. |
b39927cf4 kbuild: check for... |
1162 |
**/ |
157c23c80 kbuild: use simpl... |
1163 1164 |
static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, const char *sec) |
b39927cf4 kbuild: check for... |
1165 1166 |
{ Elf_Sym *sym; |
157c23c80 kbuild: use simpl... |
1167 |
Elf_Sym *near = NULL; |
157c23c80 kbuild: use simpl... |
1168 |
Elf_Addr distance = ~0; |
62070fa42 kbuild: kill trai... |
1169 |
|
b39927cf4 kbuild: check for... |
1170 1171 |
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { const char *symsec; |
1ce53adf1 modpost: support ... |
1172 |
if (is_shndx_special(sym->st_shndx)) |
b39927cf4 kbuild: check for... |
1173 |
continue; |
1ce53adf1 modpost: support ... |
1174 |
symsec = sec_name(elf, get_secindex(elf, sym)); |
b39927cf4 kbuild: check for... |
1175 1176 |
if (strcmp(symsec, sec) != 0) continue; |
da68d61f8 [PATCH] remove mo... |
1177 1178 |
if (!is_valid_name(elf, sym)) continue; |
b39927cf4 kbuild: check for... |
1179 |
if (sym->st_value <= addr) { |
157c23c80 kbuild: use simpl... |
1180 1181 1182 1183 1184 |
if ((addr - sym->st_value) < distance) { distance = addr - sym->st_value; near = sym; } else if ((addr - sym->st_value) == distance) { near = sym; |
43c74d179 kbuild: in the se... |
1185 |
} |
b39927cf4 kbuild: check for... |
1186 1187 |
} } |
157c23c80 kbuild: use simpl... |
1188 |
return near; |
b39927cf4 kbuild: check for... |
1189 |
} |
58fb0d4f2 kbuild: simplifie... |
1190 |
/* |
588ccd732 kbuild: add verbo... |
1191 1192 |
* Convert a section name to the function/data attribute * .init.text => __init |
588ccd732 kbuild: add verbo... |
1193 1194 |
* .memexitconst => __memconst * etc. |
cbcf14a94 scripts/mod/modpo... |
1195 1196 1197 |
* * The memory of returned value has been allocated on a heap. The user of this * method should free it after usage. |
588ccd732 kbuild: add verbo... |
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 |
*/ static char *sec2annotation(const char *s) { if (match(s, init_exit_sections)) { char *p = malloc(20); char *r = p; *p++ = '_'; *p++ = '_'; if (*s == '.') s++; while (*s && *s != '.') *p++ = *s++; *p = '\0'; if (*s == '.') s++; if (strstr(s, "rodata") != NULL) strcat(p, "const "); else if (strstr(s, "data") != NULL) strcat(p, "data "); else strcat(p, " "); |
cbcf14a94 scripts/mod/modpo... |
1220 |
return r; |
588ccd732 kbuild: add verbo... |
1221 |
} else { |
5003bab82 fix "scripts/mod/... |
1222 |
return strdup(""); |
588ccd732 kbuild: add verbo... |
1223 1224 1225 1226 1227 1228 1229 1230 |
} } static int is_function(Elf_Sym *sym) { if (sym) return ELF_ST_TYPE(sym->st_info) == STT_FUNC; else |
f666751a0 kbuild/modpost: i... |
1231 |
return -1; |
588ccd732 kbuild: add verbo... |
1232 |
} |
00759c0ea modpost: fix trai... |
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 |
static void print_section_list(const char * const list[20]) { const char *const *s = list; while (*s) { fprintf(stderr, "%s", *s); s++; if (*s) fprintf(stderr, ", "); } fprintf(stderr, " "); } |
588ccd732 kbuild: add verbo... |
1246 |
/* |
b39927cf4 kbuild: check for... |
1247 1248 |
* Print a warning about a section mismatch. * Try to find symbols near it so user can find it. |
4c8fbca58 kbuild: whitelist... |
1249 |
* Check whitelist before warning - it may be a false positive. |
58fb0d4f2 kbuild: simplifie... |
1250 |
*/ |
0d2a636ee modpost: pass aro... |
1251 1252 |
static void report_sec_mismatch(const char *modname, const struct sectioncheck *mismatch, |
58fb0d4f2 kbuild: simplifie... |
1253 1254 1255 |
const char *fromsec, unsigned long long fromaddr, const char *fromsym, |
588ccd732 kbuild: add verbo... |
1256 1257 1258 1259 1260 1261 |
int from_is_func, const char *tosec, const char *tosym, int to_is_func) { const char *from, *from_p; const char *to, *to_p; |
37ed19d5c scripts/mod/modpo... |
1262 1263 |
char *prl_from; char *prl_to; |
f666751a0 kbuild/modpost: i... |
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 |
switch (from_is_func) { case 0: from = "variable"; from_p = ""; break; case 1: from = "function"; from_p = "()"; break; default: from = "(unknown reference)"; from_p = ""; break; } switch (to_is_func) { case 0: to = "variable"; to_p = ""; break; case 1: to = "function"; to_p = "()"; break; default: to = "(unknown reference)"; to_p = ""; break; } |
588ccd732 kbuild: add verbo... |
1275 |
|
e5f95c8b7 kbuild: print onl... |
1276 1277 1278 |
sec_mismatch_count++; if (!sec_mismatch_verbose) return; |
7c0ac495e kbuild/modpost: U... |
1279 1280 1281 1282 1283 |
warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s " "to the %s %s:%s%s ", modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, tosym, to_p); |
588ccd732 kbuild: add verbo... |
1284 |
|
0d2a636ee modpost: pass aro... |
1285 |
switch (mismatch->mismatch) { |
bbd3f4fb8 modpost: give mos... |
1286 |
case TEXT_TO_ANY_INIT: |
37ed19d5c scripts/mod/modpo... |
1287 1288 |
prl_from = sec2annotation(fromsec); prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1289 |
fprintf(stderr, |
f666751a0 kbuild/modpost: i... |
1290 1291 |
"The function %s%s() references " |
588ccd732 kbuild: add verbo... |
1292 1293 1294 1295 1296 1297 |
"the %s %s%s%s. " "This is often because %s lacks a %s " "annotation or the annotation of %s is wrong. ", |
37ed19d5c scripts/mod/modpo... |
1298 1299 1300 1301 1302 |
prl_from, fromsym, to, prl_to, tosym, to_p, fromsym, prl_to, tosym); free(prl_from); free(prl_to); |
588ccd732 kbuild: add verbo... |
1303 |
break; |
bbd3f4fb8 modpost: give mos... |
1304 |
case DATA_TO_ANY_INIT: { |
37ed19d5c scripts/mod/modpo... |
1305 |
prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1306 1307 1308 1309 1310 1311 1312 |
fprintf(stderr, "The variable %s references " "the %s %s%s%s " "If the reference is valid then annotate the " |
8b8b76c04 kbuild: add hint ... |
1313 |
"variable with __init* or __refdata (see linux/init.h) " |
588ccd732 kbuild: add verbo... |
1314 1315 |
"or name the variable: ", |
37ed19d5c scripts/mod/modpo... |
1316 |
fromsym, to, prl_to, tosym, to_p); |
00759c0ea modpost: fix trai... |
1317 |
print_section_list(mismatch->symbol_white_list); |
37ed19d5c scripts/mod/modpo... |
1318 |
free(prl_to); |
588ccd732 kbuild: add verbo... |
1319 |
break; |
58fb0d4f2 kbuild: simplifie... |
1320 |
} |
bbd3f4fb8 modpost: give mos... |
1321 |
case TEXT_TO_ANY_EXIT: |
37ed19d5c scripts/mod/modpo... |
1322 |
prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1323 1324 1325 1326 1327 1328 1329 |
fprintf(stderr, "The function %s() references a %s in an exit section. " "Often the %s %s%s has valid usage outside the exit section " "and the fix is to remove the %sannotation of %s. ", |
37ed19d5c scripts/mod/modpo... |
1330 1331 |
fromsym, to, to, tosym, to_p, prl_to, tosym); free(prl_to); |
588ccd732 kbuild: add verbo... |
1332 |
break; |
bbd3f4fb8 modpost: give mos... |
1333 |
case DATA_TO_ANY_EXIT: { |
37ed19d5c scripts/mod/modpo... |
1334 |
prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 |
fprintf(stderr, "The variable %s references " "the %s %s%s%s " "If the reference is valid then annotate the " "variable with __exit* (see linux/init.h) or " "name the variable: ", |
37ed19d5c scripts/mod/modpo... |
1345 |
fromsym, to, prl_to, tosym, to_p); |
00759c0ea modpost: fix trai... |
1346 |
print_section_list(mismatch->symbol_white_list); |
37ed19d5c scripts/mod/modpo... |
1347 |
free(prl_to); |
588ccd732 kbuild: add verbo... |
1348 1349 |
break; } |
bbd3f4fb8 modpost: give mos... |
1350 1351 |
case XXXINIT_TO_SOME_INIT: case XXXEXIT_TO_SOME_EXIT: |
37ed19d5c scripts/mod/modpo... |
1352 1353 |
prl_from = sec2annotation(fromsec); prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1354 1355 1356 1357 1358 1359 1360 1361 1362 |
fprintf(stderr, "The %s %s%s%s references " "a %s %s%s%s. " "If %s is only used by %s then " "annotate %s with a matching annotation. ", |
37ed19d5c scripts/mod/modpo... |
1363 1364 |
from, prl_from, fromsym, from_p, to, prl_to, tosym, to_p, |
b1d2675a6 kbuild: fix rever... |
1365 |
tosym, fromsym, tosym); |
37ed19d5c scripts/mod/modpo... |
1366 1367 |
free(prl_from); free(prl_to); |
588ccd732 kbuild: add verbo... |
1368 |
break; |
bbd3f4fb8 modpost: give mos... |
1369 |
case ANY_INIT_TO_ANY_EXIT: |
37ed19d5c scripts/mod/modpo... |
1370 1371 |
prl_from = sec2annotation(fromsec); prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 |
fprintf(stderr, "The %s %s%s%s references " "a %s %s%s%s. " "This is often seen when error handling " "in the init function " "uses functionality in the exit path. " "The fix is often to remove the %sannotation of " "%s%s so it may be used outside an exit section. ", |
37ed19d5c scripts/mod/modpo... |
1386 1387 |
from, prl_from, fromsym, from_p, to, prl_to, tosym, to_p, |
5003bab82 fix "scripts/mod/... |
1388 |
prl_to, tosym, to_p); |
37ed19d5c scripts/mod/modpo... |
1389 1390 |
free(prl_from); free(prl_to); |
588ccd732 kbuild: add verbo... |
1391 |
break; |
bbd3f4fb8 modpost: give mos... |
1392 |
case ANY_EXIT_TO_ANY_INIT: |
37ed19d5c scripts/mod/modpo... |
1393 1394 |
prl_from = sec2annotation(fromsec); prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 |
fprintf(stderr, "The %s %s%s%s references " "a %s %s%s%s. " "This is often seen when error handling " "in the exit function " "uses functionality in the init path. " "The fix is often to remove the %sannotation of " "%s%s so it may be used outside an init section. ", |
37ed19d5c scripts/mod/modpo... |
1409 1410 1411 1412 1413 |
from, prl_from, fromsym, from_p, to, prl_to, tosym, to_p, prl_to, tosym, to_p); free(prl_from); free(prl_to); |
588ccd732 kbuild: add verbo... |
1414 1415 |
break; case EXPORT_TO_INIT_EXIT: |
37ed19d5c scripts/mod/modpo... |
1416 |
prl_to = sec2annotation(tosec); |
588ccd732 kbuild: add verbo... |
1417 1418 1419 1420 1421 1422 |
fprintf(stderr, "The symbol %s is exported and annotated %s " "Fix this by removing the %sannotation of %s " "or drop the export. ", |
37ed19d5c scripts/mod/modpo... |
1423 1424 |
tosym, prl_to, prl_to, tosym); free(prl_to); |
588ccd732 kbuild: add verbo... |
1425 1426 1427 1428 |
break; } fprintf(stderr, " "); |
58fb0d4f2 kbuild: simplifie... |
1429 1430 1431 1432 1433 1434 |
} static void check_section_mismatch(const char *modname, struct elf_info *elf, Elf_Rela *r, Elf_Sym *sym, const char *fromsec) { const char *tosec; |
0d2a636ee modpost: pass aro... |
1435 |
const struct sectioncheck *mismatch; |
58fb0d4f2 kbuild: simplifie... |
1436 |
|
1ce53adf1 modpost: support ... |
1437 |
tosec = sec_name(elf, get_secindex(elf, sym)); |
588ccd732 kbuild: add verbo... |
1438 |
mismatch = section_mismatch(fromsec, tosec); |
0d2a636ee modpost: pass aro... |
1439 |
if (mismatch) { |
588ccd732 kbuild: add verbo... |
1440 1441 |
Elf_Sym *to; Elf_Sym *from; |
58fb0d4f2 kbuild: simplifie... |
1442 |
const char *tosym; |
588ccd732 kbuild: add verbo... |
1443 |
const char *fromsym; |
58fb0d4f2 kbuild: simplifie... |
1444 |
|
588ccd732 kbuild: add verbo... |
1445 1446 1447 1448 |
from = find_elf_symbol2(elf, r->r_offset, fromsec); fromsym = sym_name(elf, from); to = find_elf_symbol(elf, r->r_addend, sym); tosym = sym_name(elf, to); |
58fb0d4f2 kbuild: simplifie... |
1449 |
|
77ab21ada Kbuild, lto, work... |
1450 1451 1452 |
if (!strncmp(fromsym, "reference___initcall", sizeof("reference___initcall")-1)) return; |
58fb0d4f2 kbuild: simplifie... |
1453 |
/* check whitelist - we may ignore it */ |
af92a82d0 modpost: make sym... |
1454 1455 |
if (secref_whitelist(mismatch, fromsec, fromsym, tosec, tosym)) { |
588ccd732 kbuild: add verbo... |
1456 1457 1458 1459 |
report_sec_mismatch(modname, mismatch, fromsec, r->r_offset, fromsym, is_function(from), tosec, tosym, is_function(to)); |
58fb0d4f2 kbuild: simplifie... |
1460 |
} |
b39927cf4 kbuild: check for... |
1461 1462 |
} } |
ae4ac1232 kbuild: make bett... |
1463 |
static unsigned int *reloc_location(struct elf_info *elf, |
5b24c0715 kbuild: code refa... |
1464 |
Elf_Shdr *sechdr, Elf_Rela *r) |
ae4ac1232 kbuild: make bett... |
1465 1466 |
{ Elf_Shdr *sechdrs = elf->sechdrs; |
6845756b2 modpost: Update 6... |
1467 |
int section = sechdr->sh_info; |
ae4ac1232 kbuild: make bett... |
1468 1469 |
return (void *)elf->hdr + sechdrs[section].sh_offset + |
731ece41f modpost: Fix addr... |
1470 |
r->r_offset; |
ae4ac1232 kbuild: make bett... |
1471 |
} |
5b24c0715 kbuild: code refa... |
1472 |
static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
ae4ac1232 kbuild: make bett... |
1473 1474 |
{ unsigned int r_typ = ELF_R_TYPE(r->r_info); |
5b24c0715 kbuild: code refa... |
1475 |
unsigned int *location = reloc_location(elf, sechdr, r); |
ae4ac1232 kbuild: make bett... |
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 |
switch (r_typ) { case R_386_32: r->r_addend = TO_NATIVE(*location); break; case R_386_PC32: r->r_addend = TO_NATIVE(*location) + 4; /* For CONFIG_RELOCATABLE=y */ if (elf->hdr->e_type == ET_EXEC) r->r_addend += r->r_offset; break; } return 0; } |
6e2e340b5 ARM: 7324/1: modp... |
1490 1491 1492 1493 1494 1495 |
#ifndef R_ARM_CALL #define R_ARM_CALL 28 #endif #ifndef R_ARM_JUMP24 #define R_ARM_JUMP24 29 #endif |
c9698e5cd ARM: 7964/1: Dete... |
1496 1497 1498 1499 1500 1501 1502 1503 1504 |
#ifndef R_ARM_THM_CALL #define R_ARM_THM_CALL 10 #endif #ifndef R_ARM_THM_JUMP24 #define R_ARM_THM_JUMP24 30 #endif #ifndef R_ARM_THM_JUMP19 #define R_ARM_THM_JUMP19 51 #endif |
5b24c0715 kbuild: code refa... |
1505 |
static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
56a974fa2 kbuild: make bett... |
1506 1507 1508 1509 1510 1511 |
{ unsigned int r_typ = ELF_R_TYPE(r->r_info); switch (r_typ) { case R_ARM_ABS32: /* From ARM ABI: (S + A) | T */ |
df578e7d8 kbuild: clean up ... |
1512 1513 |
r->r_addend = (int)(long) (elf->symtab_start + ELF_R_SYM(r->r_info)); |
56a974fa2 kbuild: make bett... |
1514 1515 |
break; case R_ARM_PC24: |
6e2e340b5 ARM: 7324/1: modp... |
1516 1517 |
case R_ARM_CALL: case R_ARM_JUMP24: |
c9698e5cd ARM: 7964/1: Dete... |
1518 1519 1520 |
case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: case R_ARM_THM_JUMP19: |
56a974fa2 kbuild: make bett... |
1521 |
/* From ARM ABI: ((S + A) | T) - P */ |
df578e7d8 kbuild: clean up ... |
1522 |
r->r_addend = (int)(long)(elf->hdr + |
5b24c0715 kbuild: code refa... |
1523 1524 |
sechdr->sh_offset + (r->r_offset - sechdr->sh_addr)); |
56a974fa2 kbuild: make bett... |
1525 1526 1527 1528 1529 1530 |
break; default: return 1; } return 0; } |
5b24c0715 kbuild: code refa... |
1531 |
static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
ae4ac1232 kbuild: make bett... |
1532 1533 |
{ unsigned int r_typ = ELF_R_TYPE(r->r_info); |
5b24c0715 kbuild: code refa... |
1534 |
unsigned int *location = reloc_location(elf, sechdr, r); |
ae4ac1232 kbuild: make bett... |
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 |
unsigned int inst; if (r_typ == R_MIPS_HI16) return 1; /* skip this */ inst = TO_NATIVE(*location); switch (r_typ) { case R_MIPS_LO16: r->r_addend = inst & 0xffff; break; case R_MIPS_26: r->r_addend = (inst & 0x03ffffff) << 2; break; case R_MIPS_32: r->r_addend = inst; break; } return 0; } |
5b24c0715 kbuild: code refa... |
1553 |
static void section_rela(const char *modname, struct elf_info *elf, |
10668220a kbuild: introduce... |
1554 |
Elf_Shdr *sechdr) |
5b24c0715 kbuild: code refa... |
1555 1556 1557 1558 1559 1560 |
{ Elf_Sym *sym; Elf_Rela *rela; Elf_Rela r; unsigned int r_sym; const char *fromsec; |
5b24c0715 kbuild: code refa... |
1561 |
|
ff13f9269 kbuild: introduce... |
1562 |
Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; |
5b24c0715 kbuild: code refa... |
1563 |
Elf_Rela *stop = (void *)start + sechdr->sh_size; |
ff13f9269 kbuild: introduce... |
1564 |
fromsec = sech_name(elf, sechdr); |
5b24c0715 kbuild: code refa... |
1565 1566 |
fromsec += strlen(".rela"); /* if from section (name) is know good then skip it */ |
b614a697d kbuild, modpost: ... |
1567 |
if (match(fromsec, section_white_list)) |
5b24c0715 kbuild: code refa... |
1568 |
return; |
e241a6303 kbuild: warn abou... |
1569 |
|
5b24c0715 kbuild: code refa... |
1570 1571 1572 |
for (rela = start; rela < stop; rela++) { r.r_offset = TO_NATIVE(rela->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 |
ff13f9269 kbuild: introduce... |
1573 |
if (elf->hdr->e_machine == EM_MIPS) { |
5b24c0715 kbuild: code refa... |
1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 |
unsigned int r_typ; r_sym = ELF64_MIPS_R_SYM(rela->r_info); r_sym = TO_NATIVE(r_sym); r_typ = ELF64_MIPS_R_TYPE(rela->r_info); r.r_info = ELF64_R_INFO(r_sym, r_typ); } else { r.r_info = TO_NATIVE(rela->r_info); r_sym = ELF_R_SYM(r.r_info); } #else r.r_info = TO_NATIVE(rela->r_info); r_sym = ELF_R_SYM(r.r_info); #endif r.r_addend = TO_NATIVE(rela->r_addend); sym = elf->symtab_start + r_sym; /* Skip special sections */ |
1ce53adf1 modpost: support ... |
1590 |
if (is_shndx_special(sym->st_shndx)) |
5b24c0715 kbuild: code refa... |
1591 |
continue; |
58fb0d4f2 kbuild: simplifie... |
1592 |
check_section_mismatch(modname, elf, &r, sym, fromsec); |
5b24c0715 kbuild: code refa... |
1593 1594 1595 1596 |
} } static void section_rel(const char *modname, struct elf_info *elf, |
10668220a kbuild: introduce... |
1597 |
Elf_Shdr *sechdr) |
5b24c0715 kbuild: code refa... |
1598 1599 1600 1601 1602 1603 |
{ Elf_Sym *sym; Elf_Rel *rel; Elf_Rela r; unsigned int r_sym; const char *fromsec; |
5b24c0715 kbuild: code refa... |
1604 |
|
ff13f9269 kbuild: introduce... |
1605 |
Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; |
5b24c0715 kbuild: code refa... |
1606 |
Elf_Rel *stop = (void *)start + sechdr->sh_size; |
ff13f9269 kbuild: introduce... |
1607 |
fromsec = sech_name(elf, sechdr); |
5b24c0715 kbuild: code refa... |
1608 1609 |
fromsec += strlen(".rel"); /* if from section (name) is know good then skip it */ |
b614a697d kbuild, modpost: ... |
1610 |
if (match(fromsec, section_white_list)) |
5b24c0715 kbuild: code refa... |
1611 1612 1613 1614 1615 |
return; for (rel = start; rel < stop; rel++) { r.r_offset = TO_NATIVE(rel->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 |
ff13f9269 kbuild: introduce... |
1616 |
if (elf->hdr->e_machine == EM_MIPS) { |
5b24c0715 kbuild: code refa... |
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 |
unsigned int r_typ; r_sym = ELF64_MIPS_R_SYM(rel->r_info); r_sym = TO_NATIVE(r_sym); r_typ = ELF64_MIPS_R_TYPE(rel->r_info); r.r_info = ELF64_R_INFO(r_sym, r_typ); } else { r.r_info = TO_NATIVE(rel->r_info); r_sym = ELF_R_SYM(r.r_info); } #else r.r_info = TO_NATIVE(rel->r_info); r_sym = ELF_R_SYM(r.r_info); #endif r.r_addend = 0; |
ff13f9269 kbuild: introduce... |
1631 |
switch (elf->hdr->e_machine) { |
5b24c0715 kbuild: code refa... |
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 |
case EM_386: if (addend_386_rel(elf, sechdr, &r)) continue; break; case EM_ARM: if (addend_arm_rel(elf, sechdr, &r)) continue; break; case EM_MIPS: if (addend_mips_rel(elf, sechdr, &r)) continue; break; } sym = elf->symtab_start + r_sym; /* Skip special sections */ |
1ce53adf1 modpost: support ... |
1647 |
if (is_shndx_special(sym->st_shndx)) |
5b24c0715 kbuild: code refa... |
1648 |
continue; |
58fb0d4f2 kbuild: simplifie... |
1649 |
check_section_mismatch(modname, elf, &r, sym, fromsec); |
5b24c0715 kbuild: code refa... |
1650 1651 |
} } |
b39927cf4 kbuild: check for... |
1652 1653 1654 1655 |
/** * A module includes a number of sections that are discarded * either when loaded or when used as built-in. * For loaded modules all functions marked __init and all data |
b595076a1 tree-wide: fix co... |
1656 |
* marked __initdata will be discarded when the module has been initialized. |
b39927cf4 kbuild: check for... |
1657 1658 |
* Likewise for modules used built-in the sections marked __exit * are discarded because __exit marked function are supposed to be called |
32be1d223 scripts/mod/modpo... |
1659 |
* only when a module is unloaded which never happens for built-in modules. |
b39927cf4 kbuild: check for... |
1660 1661 1662 1663 1664 |
* The check_sec_ref() function traverses all relocation records * to find all references to a section that reference a section that will * be discarded and warns about it. **/ static void check_sec_ref(struct module *mod, const char *modname, |
10668220a kbuild: introduce... |
1665 |
struct elf_info *elf) |
b39927cf4 kbuild: check for... |
1666 1667 |
{ int i; |
b39927cf4 kbuild: check for... |
1668 |
Elf_Shdr *sechdrs = elf->sechdrs; |
62070fa42 kbuild: kill trai... |
1669 |
|
b39927cf4 kbuild: check for... |
1670 |
/* Walk through all sections */ |
1ce53adf1 modpost: support ... |
1671 |
for (i = 0; i < elf->num_sections; i++) { |
b614a697d kbuild, modpost: ... |
1672 |
check_section(modname, elf, &elf->sechdrs[i]); |
b39927cf4 kbuild: check for... |
1673 |
/* We want to process only relocation sections and not .init */ |
5b24c0715 kbuild: code refa... |
1674 |
if (sechdrs[i].sh_type == SHT_RELA) |
10668220a kbuild: introduce... |
1675 |
section_rela(modname, elf, &elf->sechdrs[i]); |
5b24c0715 kbuild: code refa... |
1676 |
else if (sechdrs[i].sh_type == SHT_REL) |
10668220a kbuild: introduce... |
1677 |
section_rel(modname, elf, &elf->sechdrs[i]); |
b39927cf4 kbuild: check for... |
1678 1679 |
} } |
7d02b490e Kbuild, lto: Drop... |
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 |
static char *remove_dot(char *s) { char *end; int n = strcspn(s, "."); if (n > 0 && s[n] != 0) { strtoul(s + n + 1, &end, 10); if (end > s + n + 1 && (*end == '.' || *end == 0)) s[n] = 0; } return s; } |
5c3ead8c7 kbuild: apply Cod... |
1692 |
static void read_symbols(char *modname) |
1da177e4c Linux-2.6.12-rc2 |
1693 1694 1695 |
{ const char *symname; char *version; |
b817f6fef kbuild: check lic... |
1696 |
char *license; |
1da177e4c Linux-2.6.12-rc2 |
1697 1698 1699 |
struct module *mod; struct elf_info info = { }; Elf_Sym *sym; |
85bd2fddd kbuild: fix secti... |
1700 1701 |
if (!parse_elf(&info, modname)) return; |
1da177e4c Linux-2.6.12-rc2 |
1702 1703 1704 1705 1706 1707 |
mod = new_module(modname); /* When there's no vmlinux, don't print warnings about * unresolved symbols (since there'll be too many ;) */ if (is_vmlinux(modname)) { |
1da177e4c Linux-2.6.12-rc2 |
1708 |
have_vmlinux = 1; |
1da177e4c Linux-2.6.12-rc2 |
1709 1710 |
mod->skip = 1; } |
b817f6fef kbuild: check lic... |
1711 |
license = get_modinfo(info.modinfo, info.modinfo_len, "license"); |
2fa365682 kbuild: soften MO... |
1712 1713 1714 1715 1716 1717 |
if (info.modinfo && !license && !is_vmlinux(modname)) warn("modpost: missing MODULE_LICENSE() in %s " "see include/linux/module.h for " "more information ", modname); |
b817f6fef kbuild: check lic... |
1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 |
while (license) { if (license_is_gpl_compatible(license)) mod->gpl_compatible = 1; else { mod->gpl_compatible = 0; break; } license = get_next_modinfo(info.modinfo, info.modinfo_len, "license", license); } |
1da177e4c Linux-2.6.12-rc2 |
1728 |
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { |
7d02b490e Kbuild, lto: Drop... |
1729 |
symname = remove_dot(info.strtab + sym->st_name); |
1da177e4c Linux-2.6.12-rc2 |
1730 1731 1732 1733 |
handle_modversions(mod, &info, sym, symname); handle_moddevtable(mod, &info, sym, symname); } |
d1f25e665 kbuild: fix so mo... |
1734 |
if (!is_vmlinux(modname) || |
10668220a kbuild: introduce... |
1735 1736 |
(is_vmlinux(modname) && vmlinux_section_warnings)) check_sec_ref(mod, modname, &info); |
1da177e4c Linux-2.6.12-rc2 |
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 |
version = get_modinfo(info.modinfo, info.modinfo_len, "version"); if (version) maybe_frob_rcs_version(modname, version, info.modinfo, version - (char *)info.hdr); if (version || (all_versions && !is_vmlinux(modname))) get_src_version(modname, mod->srcversion, sizeof(mod->srcversion)-1); parse_elf_finish(&info); |
8c8ef42ae module: include o... |
1747 |
/* Our trick to get versioning for module struct etc. - it's |
1da177e4c Linux-2.6.12-rc2 |
1748 1749 1750 1751 |
* never passed as an argument to an exported function, so * the automatic versioning doesn't pick it up, but it's really * important anyhow */ if (modversions) |
8c8ef42ae module: include o... |
1752 |
mod->unres = alloc_symbol("module_layout", 0, mod->unres); |
1da177e4c Linux-2.6.12-rc2 |
1753 |
} |
712f9b468 modpost: add -T o... |
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 |
static void read_symbols_from_files(const char *filename) { FILE *in = stdin; char fname[PATH_MAX]; if (strcmp(filename, "-") != 0) { in = fopen(filename, "r"); if (!in) fatal("Can't open filenames file %s: %m", filename); } while (fgets(fname, PATH_MAX, in) != NULL) { if (strends(fname, " ")) fname[strlen(fname)-1] = '\0'; read_symbols(fname); } if (in != stdin) fclose(in); } |
1da177e4c Linux-2.6.12-rc2 |
1775 1776 1777 1778 1779 |
#define SZ 500 /* We first write the generated file into memory using the * following helper, then compare to the file on disk and * only update the later if anything changed */ |
5c3ead8c7 kbuild: apply Cod... |
1780 1781 |
void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, const char *fmt, ...) |
1da177e4c Linux-2.6.12-rc2 |
1782 1783 1784 1785 |
{ char tmp[SZ]; int len; va_list ap; |
62070fa42 kbuild: kill trai... |
1786 |
|
1da177e4c Linux-2.6.12-rc2 |
1787 1788 |
va_start(ap, fmt); len = vsnprintf(tmp, SZ, fmt, ap); |
7670f023a [PATCH] kbuild: f... |
1789 |
buf_write(buf, tmp, len); |
1da177e4c Linux-2.6.12-rc2 |
1790 1791 |
va_end(ap); } |
5c3ead8c7 kbuild: apply Cod... |
1792 |
void buf_write(struct buffer *buf, const char *s, int len) |
1da177e4c Linux-2.6.12-rc2 |
1793 1794 |
{ if (buf->size - buf->pos < len) { |
7670f023a [PATCH] kbuild: f... |
1795 |
buf->size += len + SZ; |
1da177e4c Linux-2.6.12-rc2 |
1796 1797 1798 1799 1800 |
buf->p = realloc(buf->p, buf->size); } strncpy(buf->p + buf->pos, s, len); buf->pos += len; } |
c96fca213 kbuild: warn when... |
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 |
static void check_for_gpl_usage(enum export exp, const char *m, const char *s) { const char *e = is_vmlinux(m) ?"":".ko"; switch (exp) { case export_gpl: fatal("modpost: GPL-incompatible module %s%s " "uses GPL-only symbol '%s' ", m, e, s); break; case export_unused_gpl: fatal("modpost: GPL-incompatible module %s%s " "uses GPL-only symbol marked UNUSED '%s' ", m, e, s); break; case export_gpl_future: warn("modpost: GPL-incompatible module %s%s " "uses future GPL-only symbol '%s' ", m, e, s); break; case export_plain: case export_unused: case export_unknown: /* ignore */ break; } } |
df578e7d8 kbuild: clean up ... |
1828 |
static void check_for_unused(enum export exp, const char *m, const char *s) |
c96fca213 kbuild: warn when... |
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 |
{ const char *e = is_vmlinux(m) ?"":".ko"; switch (exp) { case export_unused: case export_unused_gpl: warn("modpost: module %s%s " "uses symbol '%s' marked UNUSED ", m, e, s); break; default: /* ignore */ break; } } static void check_exports(struct module *mod) |
b817f6fef kbuild: check lic... |
1846 1847 1848 1849 |
{ struct symbol *s, *exp; for (s = mod->unres; s; s = s->next) { |
6449bd621 kbuild: modpost b... |
1850 |
const char *basename; |
b817f6fef kbuild: check lic... |
1851 1852 1853 |
exp = find_symbol(s->name); if (!exp || exp->module == mod) continue; |
6449bd621 kbuild: modpost b... |
1854 |
basename = strrchr(mod->name, '/'); |
b817f6fef kbuild: check lic... |
1855 1856 |
if (basename) basename++; |
c96fca213 kbuild: warn when... |
1857 1858 1859 1860 1861 |
else basename = mod->name; if (!mod->gpl_compatible) check_for_gpl_usage(exp->export, basename, exp->name); check_for_unused(exp->export, basename, exp->name); |
df578e7d8 kbuild: clean up ... |
1862 |
} |
b817f6fef kbuild: check lic... |
1863 |
} |
5c3ead8c7 kbuild: apply Cod... |
1864 1865 1866 1867 |
/** * Header for the generated file **/ static void add_header(struct buffer *b, struct module *mod) |
1da177e4c Linux-2.6.12-rc2 |
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 |
{ buf_printf(b, "#include <linux/module.h> "); buf_printf(b, "#include <linux/vermagic.h> "); buf_printf(b, "#include <linux/compiler.h> "); buf_printf(b, " "); buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING); "); buf_printf(b, " "); |
e0f244c63 asmlinkage, modul... |
1881 1882 |
buf_printf(b, "__visible struct module __this_module "); |
1da177e4c Linux-2.6.12-rc2 |
1883 1884 |
buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = { "); |
3c7ec94d2 modpost: use prop... |
1885 1886 |
buf_printf(b, "\t.name = KBUILD_MODNAME, "); |
1da177e4c Linux-2.6.12-rc2 |
1887 |
if (mod->has_init) |
3c7ec94d2 modpost: use prop... |
1888 1889 |
buf_printf(b, "\t.init = init_module, "); |
1da177e4c Linux-2.6.12-rc2 |
1890 1891 1892 |
if (mod->has_cleanup) buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD " |
3c7ec94d2 modpost: use prop... |
1893 1894 |
"\t.exit = cleanup_module, " |
1da177e4c Linux-2.6.12-rc2 |
1895 1896 |
"#endif "); |
3c7ec94d2 modpost: use prop... |
1897 1898 |
buf_printf(b, "\t.arch = MODULE_ARCH_INIT, "); |
1da177e4c Linux-2.6.12-rc2 |
1899 1900 1901 |
buf_printf(b, "}; "); } |
2449b8ba0 module,bug: Add T... |
1902 1903 1904 1905 1906 1907 1908 |
static void add_intree_flag(struct buffer *b, int is_intree) { if (is_intree) buf_printf(b, " MODULE_INFO(intree, \"Y\"); "); } |
5c7251384 Fix all -Wmissing... |
1909 |
static void add_staging_flag(struct buffer *b, const char *name) |
a9860bf05 Staging: add TAIN... |
1910 1911 1912 1913 1914 1915 1916 1917 |
{ static const char *staging_dir = "drivers/staging"; if (strncmp(staging_dir, name, strlen(staging_dir)) == 0) buf_printf(b, " MODULE_INFO(staging, \"Y\"); "); } |
5c3ead8c7 kbuild: apply Cod... |
1918 1919 1920 |
/** * Record CRCs for unresolved symbols **/ |
c53ddacdc kbuild: fail kern... |
1921 |
static int add_versions(struct buffer *b, struct module *mod) |
1da177e4c Linux-2.6.12-rc2 |
1922 1923 |
{ struct symbol *s, *exp; |
c53ddacdc kbuild: fail kern... |
1924 |
int err = 0; |
1da177e4c Linux-2.6.12-rc2 |
1925 1926 1927 1928 |
for (s = mod->unres; s; s = s->next) { exp = find_symbol(s->name); if (!exp || exp->module == mod) { |
c53ddacdc kbuild: fail kern... |
1929 |
if (have_vmlinux && !s->weak) { |
2a1166594 kbuild: distingui... |
1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 |
if (warn_unresolved) { warn("\"%s\" [%s.ko] undefined! ", s->name, mod->name); } else { merror("\"%s\" [%s.ko] undefined! ", s->name, mod->name); err = 1; } |
c53ddacdc kbuild: fail kern... |
1940 |
} |
1da177e4c Linux-2.6.12-rc2 |
1941 1942 1943 1944 1945 1946 1947 1948 |
continue; } s->module = exp->module; s->crc_valid = exp->crc_valid; s->crc = exp->crc; } if (!modversions) |
c53ddacdc kbuild: fail kern... |
1949 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
1950 1951 1952 1953 1954 |
buf_printf(b, " "); buf_printf(b, "static const struct modversion_info ____versions[] "); |
3ff6eecca remove __attribut... |
1955 1956 |
buf_printf(b, "__used "); |
1da177e4c Linux-2.6.12-rc2 |
1957 1958 1959 1960 |
buf_printf(b, "__attribute__((section(\"__versions\"))) = { "); for (s = mod->unres; s; s = s->next) { |
df578e7d8 kbuild: clean up ... |
1961 |
if (!s->module) |
1da177e4c Linux-2.6.12-rc2 |
1962 |
continue; |
1da177e4c Linux-2.6.12-rc2 |
1963 |
if (!s->crc_valid) { |
cb80514d9 kbuild: use warn(... |
1964 1965 |
warn("\"%s\" [%s.ko] has no CRC! ", |
1da177e4c Linux-2.6.12-rc2 |
1966 1967 1968 |
s->name, mod->name); continue; } |
a53a11f35 modpost: fix unwa... |
1969 1970 |
buf_printf(b, "\t{ %#8x, __VMLINUX_SYMBOL_STR(%s) }, ", |
a4b6a77b7 module: fix symbo... |
1971 |
s->crc, s->name); |
1da177e4c Linux-2.6.12-rc2 |
1972 1973 1974 1975 |
} buf_printf(b, "}; "); |
c53ddacdc kbuild: fail kern... |
1976 1977 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
1978 |
} |
5c3ead8c7 kbuild: apply Cod... |
1979 1980 |
static void add_depends(struct buffer *b, struct module *mod, struct module *modules) |
1da177e4c Linux-2.6.12-rc2 |
1981 1982 1983 1984 |
{ struct symbol *s; struct module *m; int first = 1; |
df578e7d8 kbuild: clean up ... |
1985 |
for (m = modules; m; m = m->next) |
1da177e4c Linux-2.6.12-rc2 |
1986 |
m->seen = is_vmlinux(m->name); |
1da177e4c Linux-2.6.12-rc2 |
1987 1988 1989 1990 1991 |
buf_printf(b, " "); buf_printf(b, "static const char __module_depends[] "); |
3ff6eecca remove __attribut... |
1992 1993 |
buf_printf(b, "__used "); |
1da177e4c Linux-2.6.12-rc2 |
1994 1995 1996 1997 |
buf_printf(b, "__attribute__((section(\".modinfo\"))) = "); buf_printf(b, "\"depends="); for (s = mod->unres; s; s = s->next) { |
a61b2dfd1 kbuild: fix segme... |
1998 |
const char *p; |
1da177e4c Linux-2.6.12-rc2 |
1999 2000 2001 2002 2003 2004 2005 |
if (!s->module) continue; if (s->module->seen) continue; s->module->seen = 1; |
df578e7d8 kbuild: clean up ... |
2006 2007 |
p = strrchr(s->module->name, '/'); if (p) |
a61b2dfd1 kbuild: fix segme... |
2008 2009 2010 2011 |
p++; else p = s->module->name; buf_printf(b, "%s%s", first ? "" : ",", p); |
1da177e4c Linux-2.6.12-rc2 |
2012 2013 2014 2015 2016 |
first = 0; } buf_printf(b, "\"; "); } |
5c3ead8c7 kbuild: apply Cod... |
2017 |
static void add_srcversion(struct buffer *b, struct module *mod) |
1da177e4c Linux-2.6.12-rc2 |
2018 2019 2020 2021 2022 2023 2024 2025 2026 |
{ if (mod->srcversion[0]) { buf_printf(b, " "); buf_printf(b, "MODULE_INFO(srcversion, \"%s\"); ", mod->srcversion); } } |
5c3ead8c7 kbuild: apply Cod... |
2027 |
static void write_if_changed(struct buffer *b, const char *fname) |
1da177e4c Linux-2.6.12-rc2 |
2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 |
{ char *tmp; FILE *file; struct stat st; file = fopen(fname, "r"); if (!file) goto write; if (fstat(fileno(file), &st) < 0) goto close_write; if (st.st_size != b->pos) goto close_write; tmp = NOFAIL(malloc(b->pos)); if (fread(tmp, 1, b->pos, file) != b->pos) goto free_write; if (memcmp(tmp, b->p, b->pos) != 0) goto free_write; free(tmp); fclose(file); return; free_write: free(tmp); close_write: fclose(file); write: file = fopen(fname, "w"); if (!file) { perror(fname); exit(1); } if (fwrite(b->p, 1, b->pos, file) != b->pos) { perror(fname); exit(1); } fclose(file); } |
bd5cbcedf kbuild: export-ty... |
2070 |
/* parse Module.symvers file. line format: |
534b89a9f kbuild: fix segv ... |
2071 |
* 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something] |
bd5cbcedf kbuild: export-ty... |
2072 |
**/ |
040fcc819 kbuild: improved ... |
2073 |
static void read_dump(const char *fname, unsigned int kernel) |
1da177e4c Linux-2.6.12-rc2 |
2074 2075 2076 2077 |
{ unsigned long size, pos = 0; void *file = grab_file(fname, &size); char *line; |
df578e7d8 kbuild: clean up ... |
2078 |
if (!file) |
1da177e4c Linux-2.6.12-rc2 |
2079 2080 2081 2082 |
/* No symbol versions, silently ignore */ return; while ((line = get_next_line(&pos, file, size))) { |
534b89a9f kbuild: fix segv ... |
2083 |
char *symname, *modname, *d, *export, *end; |
1da177e4c Linux-2.6.12-rc2 |
2084 2085 |
unsigned int crc; struct module *mod; |
040fcc819 kbuild: improved ... |
2086 |
struct symbol *s; |
1da177e4c Linux-2.6.12-rc2 |
2087 2088 2089 2090 2091 2092 2093 |
if (!(symname = strchr(line, '\t'))) goto fail; *symname++ = '\0'; if (!(modname = strchr(symname, '\t'))) goto fail; *modname++ = '\0'; |
9ac545b0f kbuild: fix modul... |
2094 |
if ((export = strchr(modname, '\t')) != NULL) |
bd5cbcedf kbuild: export-ty... |
2095 |
*export++ = '\0'; |
534b89a9f kbuild: fix segv ... |
2096 2097 |
if (export && ((end = strchr(export, '\t')) != NULL)) *end = '\0'; |
1da177e4c Linux-2.6.12-rc2 |
2098 2099 2100 |
crc = strtoul(line, &d, 16); if (*symname == '\0' || *modname == '\0' || *d != '\0') goto fail; |
df578e7d8 kbuild: clean up ... |
2101 2102 2103 |
mod = find_module(modname); if (!mod) { if (is_vmlinux(modname)) |
1da177e4c Linux-2.6.12-rc2 |
2104 |
have_vmlinux = 1; |
0fa3a88cf kbuild: remove po... |
2105 |
mod = new_module(modname); |
1da177e4c Linux-2.6.12-rc2 |
2106 2107 |
mod->skip = 1; } |
bd5cbcedf kbuild: export-ty... |
2108 |
s = sym_add_exported(symname, mod, export_no(export)); |
8e70c4588 kbuild: warn abou... |
2109 2110 |
s->kernel = kernel; s->preloaded = 1; |
bd5cbcedf kbuild: export-ty... |
2111 |
sym_update_crc(symname, mod, crc, export_no(export)); |
1da177e4c Linux-2.6.12-rc2 |
2112 2113 2114 2115 2116 2117 |
} return; fail: fatal("parse error in symbol dump file "); } |
040fcc819 kbuild: improved ... |
2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 |
/* For normal builds always dump all symbols. * For external modules only dump symbols * that are not read from kernel Module.symvers. **/ static int dump_sym(struct symbol *sym) { if (!external_module) return 1; if (sym->vmlinux || sym->kernel) return 0; return 1; } |
62070fa42 kbuild: kill trai... |
2130 |
|
5c3ead8c7 kbuild: apply Cod... |
2131 |
static void write_dump(const char *fname) |
1da177e4c Linux-2.6.12-rc2 |
2132 2133 2134 2135 2136 2137 2138 2139 |
{ struct buffer buf = { }; struct symbol *symbol; int n; for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { symbol = symbolhash[n]; while (symbol) { |
040fcc819 kbuild: improved ... |
2140 |
if (dump_sym(symbol)) |
bd5cbcedf kbuild: export-ty... |
2141 2142 |
buf_printf(&buf, "0x%08x\t%s\t%s\t%s ", |
62070fa42 kbuild: kill trai... |
2143 |
symbol->crc, symbol->name, |
bd5cbcedf kbuild: export-ty... |
2144 2145 |
symbol->module->name, export_str(symbol->export)); |
1da177e4c Linux-2.6.12-rc2 |
2146 2147 2148 2149 2150 |
symbol = symbol->next; } } write_if_changed(&buf, fname); } |
2d04b5ae1 kbuild: support l... |
2151 2152 2153 2154 |
struct ext_sym_list { struct ext_sym_list *next; const char *file; }; |
5c3ead8c7 kbuild: apply Cod... |
2155 |
int main(int argc, char **argv) |
1da177e4c Linux-2.6.12-rc2 |
2156 2157 2158 |
{ struct module *mod; struct buffer buf = { }; |
040fcc819 kbuild: improved ... |
2159 |
char *kernel_read = NULL, *module_read = NULL; |
712f9b468 modpost: add -T o... |
2160 |
char *dump_write = NULL, *files_source = NULL; |
1da177e4c Linux-2.6.12-rc2 |
2161 |
int opt; |
c53ddacdc kbuild: fail kern... |
2162 |
int err; |
2d04b5ae1 kbuild: support l... |
2163 2164 |
struct ext_sym_list *extsym_iter; struct ext_sym_list *extsym_start = NULL; |
1da177e4c Linux-2.6.12-rc2 |
2165 |
|
eed380f3f modpost: Optional... |
2166 |
while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:")) != -1) { |
df578e7d8 kbuild: clean up ... |
2167 2168 2169 2170 2171 2172 2173 2174 |
switch (opt) { case 'i': kernel_read = optarg; break; case 'I': module_read = optarg; external_module = 1; break; |
2d04b5ae1 kbuild: support l... |
2175 2176 2177 2178 2179 2180 2181 2182 |
case 'e': external_module = 1; extsym_iter = NOFAIL(malloc(sizeof(*extsym_iter))); extsym_iter->next = extsym_start; extsym_iter->file = optarg; extsym_start = extsym_iter; break; |
df578e7d8 kbuild: clean up ... |
2183 2184 2185 |
case 'm': modversions = 1; break; |
eed380f3f modpost: Optional... |
2186 2187 2188 |
case 'n': ignore_missing_files = 1; break; |
df578e7d8 kbuild: clean up ... |
2189 2190 2191 2192 2193 2194 2195 2196 2197 |
case 'o': dump_write = optarg; break; case 'a': all_versions = 1; break; case 's': vmlinux_section_warnings = 0; break; |
588ccd732 kbuild: add verbo... |
2198 2199 2200 |
case 'S': sec_mismatch_verbose = 0; break; |
712f9b468 modpost: add -T o... |
2201 2202 2203 |
case 'T': files_source = optarg; break; |
df578e7d8 kbuild: clean up ... |
2204 2205 2206 2207 2208 |
case 'w': warn_unresolved = 1; break; default: exit(1); |
1da177e4c Linux-2.6.12-rc2 |
2209 2210 |
} } |
040fcc819 kbuild: improved ... |
2211 2212 2213 2214 |
if (kernel_read) read_dump(kernel_read, 1); if (module_read) read_dump(module_read, 0); |
2d04b5ae1 kbuild: support l... |
2215 2216 2217 2218 2219 2220 |
while (extsym_start) { read_dump(extsym_start->file, 0); extsym_iter = extsym_start->next; free(extsym_start); extsym_start = extsym_iter; } |
1da177e4c Linux-2.6.12-rc2 |
2221 |
|
df578e7d8 kbuild: clean up ... |
2222 |
while (optind < argc) |
1da177e4c Linux-2.6.12-rc2 |
2223 |
read_symbols(argv[optind++]); |
1da177e4c Linux-2.6.12-rc2 |
2224 |
|
712f9b468 modpost: add -T o... |
2225 2226 |
if (files_source) read_symbols_from_files(files_source); |
1da177e4c Linux-2.6.12-rc2 |
2227 2228 2229 |
for (mod = modules; mod; mod = mod->next) { if (mod->skip) continue; |
c96fca213 kbuild: warn when... |
2230 |
check_exports(mod); |
b817f6fef kbuild: check lic... |
2231 |
} |
c53ddacdc kbuild: fail kern... |
2232 |
err = 0; |
b817f6fef kbuild: check lic... |
2233 |
for (mod = modules; mod; mod = mod->next) { |
666ab414f kbuild: fix a buf... |
2234 |
char fname[strlen(mod->name) + 10]; |
b817f6fef kbuild: check lic... |
2235 2236 |
if (mod->skip) continue; |
1da177e4c Linux-2.6.12-rc2 |
2237 2238 2239 2240 |
buf.pos = 0; add_header(&buf, mod); |
2449b8ba0 module,bug: Add T... |
2241 |
add_intree_flag(&buf, !external_module); |
a9860bf05 Staging: add TAIN... |
2242 |
add_staging_flag(&buf, mod->name); |
c53ddacdc kbuild: fail kern... |
2243 |
err |= add_versions(&buf, mod); |
1da177e4c Linux-2.6.12-rc2 |
2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 |
add_depends(&buf, mod, modules); add_moddevtable(&buf, mod); add_srcversion(&buf, mod); sprintf(fname, "%s.mod.c", mod->name); write_if_changed(&buf, fname); } if (dump_write) write_dump(dump_write); |
588ccd732 kbuild: add verbo... |
2254 |
if (sec_mismatch_count && !sec_mismatch_verbose) |
7c0ac495e kbuild/modpost: U... |
2255 2256 2257 2258 2259 2260 2261 |
warn("modpost: Found %d section mismatch(es). " "To see full details build your kernel with: " "'make CONFIG_DEBUG_SECTION_MISMATCH=y' ", sec_mismatch_count); |
1da177e4c Linux-2.6.12-rc2 |
2262 |
|
c53ddacdc kbuild: fail kern... |
2263 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
2264 |
} |