11da177e4SLinus Torvalds /* Postprocess module symbol versions 21da177e4SLinus Torvalds * 31da177e4SLinus Torvalds * Copyright 2003 Kai Germaschewski 41da177e4SLinus Torvalds * Copyright 2002-2004 Rusty Russell, IBM Corporation 5df578e7dSSam Ravnborg * Copyright 2006-2008 Sam Ravnborg 61da177e4SLinus Torvalds * Based in part on module-init-tools/depmod.c,file2alias 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This software may be used and distributed according to the terms 91da177e4SLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * Usage: modpost vmlinux module1.o module2.o ... 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 14b2e3e658SMathieu Desnoyers #define _GNU_SOURCE 15b2e3e658SMathieu Desnoyers #include <stdio.h> 161da177e4SLinus Torvalds #include <ctype.h> 175003bab8SAndrew Morton #include <string.h> 18712f9b46SRusty Russell #include <limits.h> 19d4ef1c30SRusty Russell #include <stdbool.h> 20eed380f3SGuenter Roeck #include <errno.h> 211da177e4SLinus Torvalds #include "modpost.h" 22b817f6feSSam Ravnborg #include "../../include/linux/license.h" 239e1b9b80SAlan Jenkins 241da177e4SLinus Torvalds /* Are we using CONFIG_MODVERSIONS? */ 257a3ee753SMathias Krause static int modversions = 0; 261da177e4SLinus Torvalds /* Warn about undefined symbols? (do so if we have vmlinux) */ 277a3ee753SMathias Krause static int have_vmlinux = 0; 281da177e4SLinus Torvalds /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ 291da177e4SLinus Torvalds static int all_versions = 0; 30040fcc81SSam Ravnborg /* If we are modposting external module set to 1 */ 31040fcc81SSam Ravnborg static int external_module = 0; 328d8d8289SSam Ravnborg /* Warn about section mismatch in vmlinux if set to 1 */ 338d8d8289SSam Ravnborg static int vmlinux_section_warnings = 1; 34c53ddacdSKirill Korotaev /* Only warn about unresolved symbols */ 35c53ddacdSKirill Korotaev static int warn_unresolved = 0; 36bd5cbcedSRam Pai /* How a symbol is exported */ 37588ccd73SSam Ravnborg static int sec_mismatch_count = 0; 3847490ec1SNicolas Boichat static int sec_mismatch_fatal = 0; 39eed380f3SGuenter Roeck /* ignore missing files */ 40eed380f3SGuenter Roeck static int ignore_missing_files; 411d082773SMatthias Maennich /* write namespace dependencies */ 421d082773SMatthias Maennich static int write_namespace_deps; 43588ccd73SSam Ravnborg 44c96fca21SSam Ravnborg enum export { 45c96fca21SSam Ravnborg export_plain, export_unused, export_gpl, 46c96fca21SSam Ravnborg export_unused_gpl, export_gpl_future, export_unknown 47c96fca21SSam Ravnborg }; 481da177e4SLinus Torvalds 494fd3e4efSWanlong Gao /* In kernel, this size is defined in linux/module.h; 504fd3e4efSWanlong Gao * here we use Elf_Addr instead of long for covering cross-compile 514fd3e4efSWanlong Gao */ 524fd3e4efSWanlong Gao 534fd3e4efSWanlong Gao #define MODULE_NAME_LEN (64 - sizeof(Elf_Addr)) 544fd3e4efSWanlong Gao 556d9a89eaSAndi Kleen #define PRINTF __attribute__ ((format (printf, 1, 2))) 566d9a89eaSAndi Kleen 576d9a89eaSAndi Kleen PRINTF void fatal(const char *fmt, ...) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds va_list arglist; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds fprintf(stderr, "FATAL: "); 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds va_start(arglist, fmt); 641da177e4SLinus Torvalds vfprintf(stderr, fmt, arglist); 651da177e4SLinus Torvalds va_end(arglist); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds exit(1); 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 706d9a89eaSAndi Kleen PRINTF void warn(const char *fmt, ...) 711da177e4SLinus Torvalds { 721da177e4SLinus Torvalds va_list arglist; 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds fprintf(stderr, "WARNING: "); 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds va_start(arglist, fmt); 771da177e4SLinus Torvalds vfprintf(stderr, fmt, arglist); 781da177e4SLinus Torvalds va_end(arglist); 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 816d9a89eaSAndi Kleen PRINTF void merror(const char *fmt, ...) 822a116659SMatthew Wilcox { 832a116659SMatthew Wilcox va_list arglist; 842a116659SMatthew Wilcox 852a116659SMatthew Wilcox fprintf(stderr, "ERROR: "); 862a116659SMatthew Wilcox 872a116659SMatthew Wilcox va_start(arglist, fmt); 882a116659SMatthew Wilcox vfprintf(stderr, fmt, arglist); 892a116659SMatthew Wilcox va_end(arglist); 902a116659SMatthew Wilcox } 912a116659SMatthew Wilcox 92d4ef1c30SRusty Russell static inline bool strends(const char *str, const char *postfix) 93d4ef1c30SRusty Russell { 94d4ef1c30SRusty Russell if (strlen(str) < strlen(postfix)) 95d4ef1c30SRusty Russell return false; 96d4ef1c30SRusty Russell 97d4ef1c30SRusty Russell return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; 98d4ef1c30SRusty Russell } 99d4ef1c30SRusty Russell 100040fcc81SSam Ravnborg static int is_vmlinux(const char *modname) 101040fcc81SSam Ravnborg { 102040fcc81SSam Ravnborg const char *myname; 103040fcc81SSam Ravnborg 104df578e7dSSam Ravnborg myname = strrchr(modname, '/'); 105df578e7dSSam Ravnborg if (myname) 106040fcc81SSam Ravnborg myname++; 107040fcc81SSam Ravnborg else 108040fcc81SSam Ravnborg myname = modname; 109040fcc81SSam Ravnborg 110741f98feSSam Ravnborg return (strcmp(myname, "vmlinux") == 0) || 111741f98feSSam Ravnborg (strcmp(myname, "vmlinux.o") == 0); 112040fcc81SSam Ravnborg } 113040fcc81SSam Ravnborg 1141da177e4SLinus Torvalds void *do_nofail(void *ptr, const char *expr) 1151da177e4SLinus Torvalds { 116df578e7dSSam Ravnborg if (!ptr) 1171da177e4SLinus Torvalds fatal("modpost: Memory allocation failure: %s.\n", expr); 118df578e7dSSam Ravnborg 1191da177e4SLinus Torvalds return ptr; 1201da177e4SLinus Torvalds } 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds /* A list of all modules we processed */ 1231da177e4SLinus Torvalds static struct module *modules; 1241da177e4SLinus Torvalds 1258b185743SMasahiro Yamada static struct module *find_module(const char *modname) 1261da177e4SLinus Torvalds { 1271da177e4SLinus Torvalds struct module *mod; 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds for (mod = modules; mod; mod = mod->next) 1301da177e4SLinus Torvalds if (strcmp(mod->name, modname) == 0) 1311da177e4SLinus Torvalds break; 1321da177e4SLinus Torvalds return mod; 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds 135d4ef1c30SRusty Russell static struct module *new_module(const char *modname) 1361da177e4SLinus Torvalds { 1371da177e4SLinus Torvalds struct module *mod; 138d4ef1c30SRusty Russell char *p; 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds mod = NOFAIL(malloc(sizeof(*mod))); 1411da177e4SLinus Torvalds memset(mod, 0, sizeof(*mod)); 1421da177e4SLinus Torvalds p = NOFAIL(strdup(modname)); 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds /* strip trailing .o */ 145d4ef1c30SRusty Russell if (strends(p, ".o")) { 146d4ef1c30SRusty Russell p[strlen(p) - 2] = '\0'; 147258f7426SFrank Rowand mod->is_dot_o = 1; 148258f7426SFrank Rowand } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds /* add to list */ 1511da177e4SLinus Torvalds mod->name = p; 152b817f6feSSam Ravnborg mod->gpl_compatible = -1; 1531da177e4SLinus Torvalds mod->next = modules; 1541da177e4SLinus Torvalds modules = mod; 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds return mod; 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds /* A hash of all exported symbols, 1601da177e4SLinus Torvalds * struct symbol is also used for lists of unresolved symbols */ 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds #define SYMBOL_HASH_SIZE 1024 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds struct symbol { 1651da177e4SLinus Torvalds struct symbol *next; 1661da177e4SLinus Torvalds struct module *module; 1671da177e4SLinus Torvalds unsigned int crc; 1681da177e4SLinus Torvalds int crc_valid; 169cb9b55d2SMatthias Maennich const char *namespace; 1701da177e4SLinus Torvalds unsigned int weak:1; 171040fcc81SSam Ravnborg unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */ 172040fcc81SSam Ravnborg unsigned int kernel:1; /* 1 if symbol is from kernel 173040fcc81SSam Ravnborg * (only for external modules) **/ 174b6568b1aSRusty Russell unsigned int preloaded:1; /* 1 if symbol from Module.symvers, or crc */ 17515bfc234SDenis Efremov unsigned int is_static:1; /* 1 if symbol is not global */ 176bd5cbcedSRam Pai enum export export; /* Type of export */ 1771da177e4SLinus Torvalds char name[0]; 1781da177e4SLinus Torvalds }; 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds static struct symbol *symbolhash[SYMBOL_HASH_SIZE]; 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds /* This is based on the hash agorithm from gdbm, via tdb */ 1831da177e4SLinus Torvalds static inline unsigned int tdb_hash(const char *name) 1841da177e4SLinus Torvalds { 1851da177e4SLinus Torvalds unsigned value; /* Used to compute the hash value. */ 1861da177e4SLinus Torvalds unsigned i; /* Used to cycle through random values. */ 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds /* Set the initial value from the key size. */ 1891da177e4SLinus Torvalds for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) 1901da177e4SLinus Torvalds value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds return (1103515243 * value + 12345); 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 1955c3ead8cSSam Ravnborg /** 1965c3ead8cSSam Ravnborg * Allocate a new symbols for use in the hash of exported symbols or 1975c3ead8cSSam Ravnborg * the list of unresolved symbols per module 1985c3ead8cSSam Ravnborg **/ 1995c3ead8cSSam Ravnborg static struct symbol *alloc_symbol(const char *name, unsigned int weak, 2005c3ead8cSSam Ravnborg struct symbol *next) 2011da177e4SLinus Torvalds { 2021da177e4SLinus Torvalds struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds memset(s, 0, sizeof(*s)); 2051da177e4SLinus Torvalds strcpy(s->name, name); 2061da177e4SLinus Torvalds s->weak = weak; 2071da177e4SLinus Torvalds s->next = next; 20815bfc234SDenis Efremov s->is_static = 1; 2091da177e4SLinus Torvalds return s; 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds /* For the hash of exported symbols */ 213bd5cbcedSRam Pai static struct symbol *new_symbol(const char *name, struct module *module, 214bd5cbcedSRam Pai enum export export) 2151da177e4SLinus Torvalds { 2161da177e4SLinus Torvalds unsigned int hash; 2171da177e4SLinus Torvalds struct symbol *new; 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds hash = tdb_hash(name) % SYMBOL_HASH_SIZE; 2201da177e4SLinus Torvalds new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); 2211da177e4SLinus Torvalds new->module = module; 222bd5cbcedSRam Pai new->export = export; 223040fcc81SSam Ravnborg return new; 2241da177e4SLinus Torvalds } 2251da177e4SLinus Torvalds 2265c3ead8cSSam Ravnborg static struct symbol *find_symbol(const char *name) 2271da177e4SLinus Torvalds { 2281da177e4SLinus Torvalds struct symbol *s; 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* For our purposes, .foo matches foo. PPC64 needs this. */ 2311da177e4SLinus Torvalds if (name[0] == '.') 2321da177e4SLinus Torvalds name++; 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) { 2351da177e4SLinus Torvalds if (strcmp(s->name, name) == 0) 2361da177e4SLinus Torvalds return s; 2371da177e4SLinus Torvalds } 2381da177e4SLinus Torvalds return NULL; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds 241cb9b55d2SMatthias Maennich static bool contains_namespace(struct namespace_list *list, 242cb9b55d2SMatthias Maennich const char *namespace) 243cb9b55d2SMatthias Maennich { 244cb9b55d2SMatthias Maennich struct namespace_list *ns_entry; 245cb9b55d2SMatthias Maennich 246cb9b55d2SMatthias Maennich for (ns_entry = list; ns_entry != NULL; ns_entry = ns_entry->next) 247cb9b55d2SMatthias Maennich if (strcmp(ns_entry->namespace, namespace) == 0) 248cb9b55d2SMatthias Maennich return true; 249cb9b55d2SMatthias Maennich 250cb9b55d2SMatthias Maennich return false; 251cb9b55d2SMatthias Maennich } 252cb9b55d2SMatthias Maennich 253cb9b55d2SMatthias Maennich static void add_namespace(struct namespace_list **list, const char *namespace) 254cb9b55d2SMatthias Maennich { 255cb9b55d2SMatthias Maennich struct namespace_list *ns_entry; 256cb9b55d2SMatthias Maennich 257cb9b55d2SMatthias Maennich if (!contains_namespace(*list, namespace)) { 258cb9b55d2SMatthias Maennich ns_entry = NOFAIL(malloc(sizeof(struct namespace_list) + 259cb9b55d2SMatthias Maennich strlen(namespace) + 1)); 260cb9b55d2SMatthias Maennich strcpy(ns_entry->namespace, namespace); 261cb9b55d2SMatthias Maennich ns_entry->next = *list; 262cb9b55d2SMatthias Maennich *list = ns_entry; 263cb9b55d2SMatthias Maennich } 264cb9b55d2SMatthias Maennich } 265cb9b55d2SMatthias Maennich 266cb9b55d2SMatthias Maennich static bool module_imports_namespace(struct module *module, 267cb9b55d2SMatthias Maennich const char *namespace) 268cb9b55d2SMatthias Maennich { 269cb9b55d2SMatthias Maennich return contains_namespace(module->imported_namespaces, namespace); 270cb9b55d2SMatthias Maennich } 271cb9b55d2SMatthias Maennich 2727a3ee753SMathias Krause static const struct { 273bd5cbcedSRam Pai const char *str; 274bd5cbcedSRam Pai enum export export; 275bd5cbcedSRam Pai } export_list[] = { 276bd5cbcedSRam Pai { .str = "EXPORT_SYMBOL", .export = export_plain }, 277c96fca21SSam Ravnborg { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, 278bd5cbcedSRam Pai { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, 279c96fca21SSam Ravnborg { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, 280bd5cbcedSRam Pai { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, 281bd5cbcedSRam Pai { .str = "(unknown)", .export = export_unknown }, 282bd5cbcedSRam Pai }; 283bd5cbcedSRam Pai 284bd5cbcedSRam Pai 285bd5cbcedSRam Pai static const char *export_str(enum export ex) 286bd5cbcedSRam Pai { 287bd5cbcedSRam Pai return export_list[ex].str; 288bd5cbcedSRam Pai } 289bd5cbcedSRam Pai 290bd5cbcedSRam Pai static enum export export_no(const char *s) 291bd5cbcedSRam Pai { 292bd5cbcedSRam Pai int i; 293df578e7dSSam Ravnborg 294534b89a9SSam Ravnborg if (!s) 295534b89a9SSam Ravnborg return export_unknown; 296bd5cbcedSRam Pai for (i = 0; export_list[i].export != export_unknown; i++) { 297bd5cbcedSRam Pai if (strcmp(export_list[i].str, s) == 0) 298bd5cbcedSRam Pai return export_list[i].export; 299bd5cbcedSRam Pai } 300bd5cbcedSRam Pai return export_unknown; 301bd5cbcedSRam Pai } 302bd5cbcedSRam Pai 3036124c04cSMasahiro Yamada static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) 3046124c04cSMasahiro Yamada { 3056124c04cSMasahiro Yamada return (void *)elf->hdr + 3066124c04cSMasahiro Yamada elf->sechdrs[elf->secindex_strings].sh_offset + 3076124c04cSMasahiro Yamada sechdr->sh_name; 3086124c04cSMasahiro Yamada } 3096124c04cSMasahiro Yamada 3106124c04cSMasahiro Yamada static const char *sec_name(struct elf_info *elf, int secindex) 3116124c04cSMasahiro Yamada { 3126124c04cSMasahiro Yamada return sech_name(elf, &elf->sechdrs[secindex]); 3136124c04cSMasahiro Yamada } 31462a26356SAlessio Igor Bogani 31562a26356SAlessio Igor Bogani #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) 31662a26356SAlessio Igor Bogani 31762a26356SAlessio Igor Bogani static enum export export_from_secname(struct elf_info *elf, unsigned int sec) 31862a26356SAlessio Igor Bogani { 31962a26356SAlessio Igor Bogani const char *secname = sec_name(elf, sec); 32062a26356SAlessio Igor Bogani 32162a26356SAlessio Igor Bogani if (strstarts(secname, "___ksymtab+")) 32262a26356SAlessio Igor Bogani return export_plain; 32362a26356SAlessio Igor Bogani else if (strstarts(secname, "___ksymtab_unused+")) 32462a26356SAlessio Igor Bogani return export_unused; 32562a26356SAlessio Igor Bogani else if (strstarts(secname, "___ksymtab_gpl+")) 32662a26356SAlessio Igor Bogani return export_gpl; 32762a26356SAlessio Igor Bogani else if (strstarts(secname, "___ksymtab_unused_gpl+")) 32862a26356SAlessio Igor Bogani return export_unused_gpl; 32962a26356SAlessio Igor Bogani else if (strstarts(secname, "___ksymtab_gpl_future+")) 33062a26356SAlessio Igor Bogani return export_gpl_future; 33162a26356SAlessio Igor Bogani else 33262a26356SAlessio Igor Bogani return export_unknown; 33362a26356SAlessio Igor Bogani } 33462a26356SAlessio Igor Bogani 3351ce53adfSDenys Vlasenko static enum export export_from_sec(struct elf_info *elf, unsigned int sec) 336bd5cbcedSRam Pai { 337bd5cbcedSRam Pai if (sec == elf->export_sec) 338bd5cbcedSRam Pai return export_plain; 339c96fca21SSam Ravnborg else if (sec == elf->export_unused_sec) 340c96fca21SSam Ravnborg return export_unused; 341bd5cbcedSRam Pai else if (sec == elf->export_gpl_sec) 342bd5cbcedSRam Pai return export_gpl; 343c96fca21SSam Ravnborg else if (sec == elf->export_unused_gpl_sec) 344c96fca21SSam Ravnborg return export_unused_gpl; 345bd5cbcedSRam Pai else if (sec == elf->export_gpl_future_sec) 346bd5cbcedSRam Pai return export_gpl_future; 347bd5cbcedSRam Pai else 348bd5cbcedSRam Pai return export_unknown; 349bd5cbcedSRam Pai } 350bd5cbcedSRam Pai 351cb9b55d2SMatthias Maennich static const char *sym_extract_namespace(const char **symname) 352cb9b55d2SMatthias Maennich { 353cb9b55d2SMatthias Maennich size_t n; 354cb9b55d2SMatthias Maennich char *dupsymname; 355cb9b55d2SMatthias Maennich 356cb9b55d2SMatthias Maennich n = strcspn(*symname, "."); 357cb9b55d2SMatthias Maennich if (n < strlen(*symname) - 1) { 358cb9b55d2SMatthias Maennich dupsymname = NOFAIL(strdup(*symname)); 359cb9b55d2SMatthias Maennich dupsymname[n] = '\0'; 360cb9b55d2SMatthias Maennich *symname = dupsymname; 361cb9b55d2SMatthias Maennich return dupsymname + n + 1; 362cb9b55d2SMatthias Maennich } 363cb9b55d2SMatthias Maennich 364cb9b55d2SMatthias Maennich return NULL; 365cb9b55d2SMatthias Maennich } 366cb9b55d2SMatthias Maennich 3675c3ead8cSSam Ravnborg /** 3685c3ead8cSSam Ravnborg * Add an exported symbol - it may have already been added without a 3695c3ead8cSSam Ravnborg * CRC, in this case just update the CRC 3705c3ead8cSSam Ravnborg **/ 371cb9b55d2SMatthias Maennich static struct symbol *sym_add_exported(const char *name, const char *namespace, 372cb9b55d2SMatthias Maennich struct module *mod, enum export export) 3731da177e4SLinus Torvalds { 3741da177e4SLinus Torvalds struct symbol *s = find_symbol(name); 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds if (!s) { 377bd5cbcedSRam Pai s = new_symbol(name, mod, export); 378cb9b55d2SMatthias Maennich s->namespace = namespace; 3798e70c458SSam Ravnborg } else { 3808e70c458SSam Ravnborg if (!s->preloaded) { 381cb9b55d2SMatthias Maennich warn("%s: '%s' exported twice. Previous export was in %s%s\n", 382cb9b55d2SMatthias Maennich mod->name, name, s->module->name, 3838e70c458SSam Ravnborg is_vmlinux(s->module->name) ? "" : ".ko"); 3844b21960fSTrent Piepho } else { 385baec30e4SPaul Bolle /* In case Module.symvers was out of date */ 3864b21960fSTrent Piepho s->module = mod; 3871da177e4SLinus Torvalds } 3881da177e4SLinus Torvalds } 3898e70c458SSam Ravnborg s->preloaded = 0; 390040fcc81SSam Ravnborg s->vmlinux = is_vmlinux(mod->name); 391040fcc81SSam Ravnborg s->kernel = 0; 392bd5cbcedSRam Pai s->export = export; 393040fcc81SSam Ravnborg return s; 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds 396040fcc81SSam Ravnborg static void sym_update_crc(const char *name, struct module *mod, 397bd5cbcedSRam Pai unsigned int crc, enum export export) 398040fcc81SSam Ravnborg { 399040fcc81SSam Ravnborg struct symbol *s = find_symbol(name); 400040fcc81SSam Ravnborg 401b6568b1aSRusty Russell if (!s) { 402bd5cbcedSRam Pai s = new_symbol(name, mod, export); 403b6568b1aSRusty Russell /* Don't complain when we find it later. */ 404b6568b1aSRusty Russell s->preloaded = 1; 405b6568b1aSRusty Russell } 406040fcc81SSam Ravnborg s->crc = crc; 4071da177e4SLinus Torvalds s->crc_valid = 1; 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds 4105c3ead8cSSam Ravnborg void *grab_file(const char *filename, unsigned long *size) 4111da177e4SLinus Torvalds { 4121da177e4SLinus Torvalds struct stat st; 413eb3d5cc6SJesper Juhl void *map = MAP_FAILED; 4141da177e4SLinus Torvalds int fd; 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds fd = open(filename, O_RDONLY); 417eb3d5cc6SJesper Juhl if (fd < 0) 4181da177e4SLinus Torvalds return NULL; 419eb3d5cc6SJesper Juhl if (fstat(fd, &st)) 420eb3d5cc6SJesper Juhl goto failed; 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds *size = st.st_size; 4231da177e4SLinus Torvalds map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 4241da177e4SLinus Torvalds 425eb3d5cc6SJesper Juhl failed: 426eb3d5cc6SJesper Juhl close(fd); 4271da177e4SLinus Torvalds if (map == MAP_FAILED) 4281da177e4SLinus Torvalds return NULL; 4291da177e4SLinus Torvalds return map; 4301da177e4SLinus Torvalds } 4311da177e4SLinus Torvalds 4325c3ead8cSSam Ravnborg /** 4335c3ead8cSSam Ravnborg * Return a copy of the next line in a mmap'ed file. 4345c3ead8cSSam Ravnborg * spaces in the beginning of the line is trimmed away. 4355c3ead8cSSam Ravnborg * Return a pointer to a static buffer. 4365c3ead8cSSam Ravnborg **/ 4375c3ead8cSSam Ravnborg char *get_next_line(unsigned long *pos, void *file, unsigned long size) 4381da177e4SLinus Torvalds { 4391da177e4SLinus Torvalds static char line[4096]; 4401da177e4SLinus Torvalds int skip = 1; 4411da177e4SLinus Torvalds size_t len = 0; 4421da177e4SLinus Torvalds signed char *p = (signed char *)file + *pos; 4431da177e4SLinus Torvalds char *s = line; 4441da177e4SLinus Torvalds 445df578e7dSSam Ravnborg for (; *pos < size ; (*pos)++) { 4461da177e4SLinus Torvalds if (skip && isspace(*p)) { 4471da177e4SLinus Torvalds p++; 4481da177e4SLinus Torvalds continue; 4491da177e4SLinus Torvalds } 4501da177e4SLinus Torvalds skip = 0; 4511da177e4SLinus Torvalds if (*p != '\n' && (*pos < size)) { 4521da177e4SLinus Torvalds len++; 4531da177e4SLinus Torvalds *s++ = *p++; 4541da177e4SLinus Torvalds if (len > 4095) 4551da177e4SLinus Torvalds break; /* Too long, stop */ 4561da177e4SLinus Torvalds } else { 4571da177e4SLinus Torvalds /* End of string */ 4581da177e4SLinus Torvalds *s = '\0'; 4591da177e4SLinus Torvalds return line; 4601da177e4SLinus Torvalds } 4611da177e4SLinus Torvalds } 4621da177e4SLinus Torvalds /* End of buffer */ 4631da177e4SLinus Torvalds return NULL; 4641da177e4SLinus Torvalds } 4651da177e4SLinus Torvalds 4665c3ead8cSSam Ravnborg void release_file(void *file, unsigned long size) 4671da177e4SLinus Torvalds { 4681da177e4SLinus Torvalds munmap(file, size); 4691da177e4SLinus Torvalds } 4701da177e4SLinus Torvalds 47185bd2fddSSam Ravnborg static int parse_elf(struct elf_info *info, const char *filename) 4721da177e4SLinus Torvalds { 4731da177e4SLinus Torvalds unsigned int i; 47485bd2fddSSam Ravnborg Elf_Ehdr *hdr; 4751da177e4SLinus Torvalds Elf_Shdr *sechdrs; 4761da177e4SLinus Torvalds Elf_Sym *sym; 4771ce53adfSDenys Vlasenko const char *secstrings; 4781ce53adfSDenys Vlasenko unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U; 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds hdr = grab_file(filename, &info->size); 4811da177e4SLinus Torvalds if (!hdr) { 482eed380f3SGuenter Roeck if (ignore_missing_files) { 483eed380f3SGuenter Roeck fprintf(stderr, "%s: %s (ignored)\n", filename, 484eed380f3SGuenter Roeck strerror(errno)); 485eed380f3SGuenter Roeck return 0; 486eed380f3SGuenter Roeck } 4871da177e4SLinus Torvalds perror(filename); 4886803dc0eSSam Ravnborg exit(1); 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds info->hdr = hdr; 49185bd2fddSSam Ravnborg if (info->size < sizeof(*hdr)) { 49285bd2fddSSam Ravnborg /* file too small, assume this is an empty .o file */ 49385bd2fddSSam Ravnborg return 0; 49485bd2fddSSam Ravnborg } 49585bd2fddSSam Ravnborg /* Is this a valid ELF file? */ 49685bd2fddSSam Ravnborg if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || 49785bd2fddSSam Ravnborg (hdr->e_ident[EI_MAG1] != ELFMAG1) || 49885bd2fddSSam Ravnborg (hdr->e_ident[EI_MAG2] != ELFMAG2) || 49985bd2fddSSam Ravnborg (hdr->e_ident[EI_MAG3] != ELFMAG3)) { 50085bd2fddSSam Ravnborg /* Not an ELF file - silently ignore it */ 50185bd2fddSSam Ravnborg return 0; 50285bd2fddSSam Ravnborg } 5031da177e4SLinus Torvalds /* Fix endianness in ELF header */ 504ae4ac123SAtsushi Nemoto hdr->e_type = TO_NATIVE(hdr->e_type); 5057d875a02SAnders Kaseorg hdr->e_machine = TO_NATIVE(hdr->e_machine); 5067d875a02SAnders Kaseorg hdr->e_version = TO_NATIVE(hdr->e_version); 5077d875a02SAnders Kaseorg hdr->e_entry = TO_NATIVE(hdr->e_entry); 5087d875a02SAnders Kaseorg hdr->e_phoff = TO_NATIVE(hdr->e_phoff); 5097d875a02SAnders Kaseorg hdr->e_shoff = TO_NATIVE(hdr->e_shoff); 5107d875a02SAnders Kaseorg hdr->e_flags = TO_NATIVE(hdr->e_flags); 5117d875a02SAnders Kaseorg hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize); 5127d875a02SAnders Kaseorg hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize); 5137d875a02SAnders Kaseorg hdr->e_phnum = TO_NATIVE(hdr->e_phnum); 5147d875a02SAnders Kaseorg hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize); 5157d875a02SAnders Kaseorg hdr->e_shnum = TO_NATIVE(hdr->e_shnum); 5167d875a02SAnders Kaseorg hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); 5171da177e4SLinus Torvalds sechdrs = (void *)hdr + hdr->e_shoff; 5181da177e4SLinus Torvalds info->sechdrs = sechdrs; 5191da177e4SLinus Torvalds 520a83710e5SPetr Stetiar /* Check if file offset is correct */ 521a83710e5SPetr Stetiar if (hdr->e_shoff > info->size) { 522df578e7dSSam Ravnborg fatal("section header offset=%lu in file '%s' is bigger than " 523df578e7dSSam Ravnborg "filesize=%lu\n", (unsigned long)hdr->e_shoff, 524df578e7dSSam Ravnborg filename, info->size); 525a83710e5SPetr Stetiar return 0; 526a83710e5SPetr Stetiar } 527a83710e5SPetr Stetiar 5286845756bSAnders Kaseorg if (hdr->e_shnum == SHN_UNDEF) { 5291ce53adfSDenys Vlasenko /* 5301ce53adfSDenys Vlasenko * There are more than 64k sections, 5311ce53adfSDenys Vlasenko * read count from .sh_size. 5321ce53adfSDenys Vlasenko */ 5331ce53adfSDenys Vlasenko info->num_sections = TO_NATIVE(sechdrs[0].sh_size); 5341ce53adfSDenys Vlasenko } 5351ce53adfSDenys Vlasenko else { 5361ce53adfSDenys Vlasenko info->num_sections = hdr->e_shnum; 5371ce53adfSDenys Vlasenko } 5381ce53adfSDenys Vlasenko if (hdr->e_shstrndx == SHN_XINDEX) { 5396845756bSAnders Kaseorg info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link); 5401ce53adfSDenys Vlasenko } 5411ce53adfSDenys Vlasenko else { 5421ce53adfSDenys Vlasenko info->secindex_strings = hdr->e_shstrndx; 5431ce53adfSDenys Vlasenko } 5441ce53adfSDenys Vlasenko 5451da177e4SLinus Torvalds /* Fix endianness in section headers */ 5461ce53adfSDenys Vlasenko for (i = 0; i < info->num_sections; i++) { 5477d875a02SAnders Kaseorg sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); 5481da177e4SLinus Torvalds sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); 5497d875a02SAnders Kaseorg sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); 5507d875a02SAnders Kaseorg sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); 5511da177e4SLinus Torvalds sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); 5521da177e4SLinus Torvalds sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); 5531da177e4SLinus Torvalds sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); 554ae4ac123SAtsushi Nemoto sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); 5557d875a02SAnders Kaseorg sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign); 5567d875a02SAnders Kaseorg sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds /* Find symbol table. */ 5591ce53adfSDenys Vlasenko secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset; 5601ce53adfSDenys Vlasenko for (i = 1; i < info->num_sections; i++) { 561bd5cbcedSRam Pai const char *secname; 56256fc82c5STejun Heo int nobits = sechdrs[i].sh_type == SHT_NOBITS; 5631da177e4SLinus Torvalds 56456fc82c5STejun Heo if (!nobits && sechdrs[i].sh_offset > info->size) { 565df578e7dSSam Ravnborg fatal("%s is truncated. sechdrs[i].sh_offset=%lu > " 566df578e7dSSam Ravnborg "sizeof(*hrd)=%zu\n", filename, 567df578e7dSSam Ravnborg (unsigned long)sechdrs[i].sh_offset, 568df578e7dSSam Ravnborg sizeof(*hdr)); 56985bd2fddSSam Ravnborg return 0; 57085bd2fddSSam Ravnborg } 571bd5cbcedSRam Pai secname = secstrings + sechdrs[i].sh_name; 572bd5cbcedSRam Pai if (strcmp(secname, ".modinfo") == 0) { 57356fc82c5STejun Heo if (nobits) 57456fc82c5STejun Heo fatal("%s has NOBITS .modinfo\n", filename); 5751da177e4SLinus Torvalds info->modinfo = (void *)hdr + sechdrs[i].sh_offset; 5761da177e4SLinus Torvalds info->modinfo_len = sechdrs[i].sh_size; 577bd5cbcedSRam Pai } else if (strcmp(secname, "__ksymtab") == 0) 578bd5cbcedSRam Pai info->export_sec = i; 579c96fca21SSam Ravnborg else if (strcmp(secname, "__ksymtab_unused") == 0) 580c96fca21SSam Ravnborg info->export_unused_sec = i; 581bd5cbcedSRam Pai else if (strcmp(secname, "__ksymtab_gpl") == 0) 582bd5cbcedSRam Pai info->export_gpl_sec = i; 583c96fca21SSam Ravnborg else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) 584c96fca21SSam Ravnborg info->export_unused_gpl_sec = i; 585bd5cbcedSRam Pai else if (strcmp(secname, "__ksymtab_gpl_future") == 0) 586bd5cbcedSRam Pai info->export_gpl_future_sec = i; 587bd5cbcedSRam Pai 5881ce53adfSDenys Vlasenko if (sechdrs[i].sh_type == SHT_SYMTAB) { 5891ce53adfSDenys Vlasenko unsigned int sh_link_idx; 5901ce53adfSDenys Vlasenko symtab_idx = i; 5911ce53adfSDenys Vlasenko info->symtab_start = (void *)hdr + 5921ce53adfSDenys Vlasenko sechdrs[i].sh_offset; 5931ce53adfSDenys Vlasenko info->symtab_stop = (void *)hdr + 5941ce53adfSDenys Vlasenko sechdrs[i].sh_offset + sechdrs[i].sh_size; 5956845756bSAnders Kaseorg sh_link_idx = sechdrs[i].sh_link; 5961da177e4SLinus Torvalds info->strtab = (void *)hdr + 5971ce53adfSDenys Vlasenko sechdrs[sh_link_idx].sh_offset; 5981ce53adfSDenys Vlasenko } 5991ce53adfSDenys Vlasenko 6001ce53adfSDenys Vlasenko /* 32bit section no. table? ("more than 64k sections") */ 6011ce53adfSDenys Vlasenko if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) { 6021ce53adfSDenys Vlasenko symtab_shndx_idx = i; 6031ce53adfSDenys Vlasenko info->symtab_shndx_start = (void *)hdr + 6041ce53adfSDenys Vlasenko sechdrs[i].sh_offset; 6051ce53adfSDenys Vlasenko info->symtab_shndx_stop = (void *)hdr + 6061ce53adfSDenys Vlasenko sechdrs[i].sh_offset + sechdrs[i].sh_size; 6071ce53adfSDenys Vlasenko } 6081da177e4SLinus Torvalds } 609df578e7dSSam Ravnborg if (!info->symtab_start) 610cb80514dSSam Ravnborg fatal("%s has no symtab?\n", filename); 611df578e7dSSam Ravnborg 6121da177e4SLinus Torvalds /* Fix endianness in symbols */ 6131da177e4SLinus Torvalds for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { 6141da177e4SLinus Torvalds sym->st_shndx = TO_NATIVE(sym->st_shndx); 6151da177e4SLinus Torvalds sym->st_name = TO_NATIVE(sym->st_name); 6161da177e4SLinus Torvalds sym->st_value = TO_NATIVE(sym->st_value); 6171da177e4SLinus Torvalds sym->st_size = TO_NATIVE(sym->st_size); 6181da177e4SLinus Torvalds } 6191ce53adfSDenys Vlasenko 6201ce53adfSDenys Vlasenko if (symtab_shndx_idx != ~0U) { 6211ce53adfSDenys Vlasenko Elf32_Word *p; 6226845756bSAnders Kaseorg if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link) 6231ce53adfSDenys Vlasenko fatal("%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n", 6246845756bSAnders Kaseorg filename, sechdrs[symtab_shndx_idx].sh_link, 6251ce53adfSDenys Vlasenko symtab_idx); 6261ce53adfSDenys Vlasenko /* Fix endianness */ 6271ce53adfSDenys Vlasenko for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; 6281ce53adfSDenys Vlasenko p++) 6291ce53adfSDenys Vlasenko *p = TO_NATIVE(*p); 6301ce53adfSDenys Vlasenko } 6311ce53adfSDenys Vlasenko 63285bd2fddSSam Ravnborg return 1; 6331da177e4SLinus Torvalds } 6341da177e4SLinus Torvalds 6355c3ead8cSSam Ravnborg static void parse_elf_finish(struct elf_info *info) 6361da177e4SLinus Torvalds { 6371da177e4SLinus Torvalds release_file(info->hdr, info->size); 6381da177e4SLinus Torvalds } 6391da177e4SLinus Torvalds 6404d7365d6SSam Ravnborg static int ignore_undef_symbol(struct elf_info *info, const char *symname) 6414d7365d6SSam Ravnborg { 6424d7365d6SSam Ravnborg /* ignore __this_module, it will be resolved shortly */ 643b2c5cdcfSMasahiro Yamada if (strcmp(symname, "__this_module") == 0) 6444d7365d6SSam Ravnborg return 1; 6454d7365d6SSam Ravnborg /* ignore global offset table */ 6464d7365d6SSam Ravnborg if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) 6474d7365d6SSam Ravnborg return 1; 6484d7365d6SSam Ravnborg if (info->hdr->e_machine == EM_PPC) 6494d7365d6SSam Ravnborg /* Special register function linked on all modules during final link of .ko */ 650d62c4765SMasahiro Yamada if (strstarts(symname, "_restgpr_") || 651d62c4765SMasahiro Yamada strstarts(symname, "_savegpr_") || 652d62c4765SMasahiro Yamada strstarts(symname, "_rest32gpr_") || 653d62c4765SMasahiro Yamada strstarts(symname, "_save32gpr_") || 654d62c4765SMasahiro Yamada strstarts(symname, "_restvr_") || 655d62c4765SMasahiro Yamada strstarts(symname, "_savevr_")) 6564d7365d6SSam Ravnborg return 1; 6577fca5dc8SStephen Rothwell if (info->hdr->e_machine == EM_PPC64) 6587fca5dc8SStephen Rothwell /* Special register function linked on all modules during final link of .ko */ 659d62c4765SMasahiro Yamada if (strstarts(symname, "_restgpr0_") || 660d62c4765SMasahiro Yamada strstarts(symname, "_savegpr0_") || 661d62c4765SMasahiro Yamada strstarts(symname, "_restvr_") || 662d62c4765SMasahiro Yamada strstarts(symname, "_savevr_") || 663c153693dSAlan Modra strcmp(symname, ".TOC.") == 0) 6647fca5dc8SStephen Rothwell return 1; 6654d7365d6SSam Ravnborg /* Do not ignore this symbol */ 6664d7365d6SSam Ravnborg return 0; 6674d7365d6SSam Ravnborg } 6684d7365d6SSam Ravnborg 6695c3ead8cSSam Ravnborg static void handle_modversions(struct module *mod, struct elf_info *info, 6701da177e4SLinus Torvalds Elf_Sym *sym, const char *symname) 6711da177e4SLinus Torvalds { 6721da177e4SLinus Torvalds unsigned int crc; 67362a26356SAlessio Igor Bogani enum export export; 674d8c1eb86SNicholas Piggin bool is_crc = false; 675cb9b55d2SMatthias Maennich const char *name, *namespace; 67662a26356SAlessio Igor Bogani 677258f7426SFrank Rowand if ((!is_vmlinux(mod->name) || mod->is_dot_o) && 678d62c4765SMasahiro Yamada strstarts(symname, "__ksymtab")) 67962a26356SAlessio Igor Bogani export = export_from_secname(info, get_secindex(info, sym)); 68062a26356SAlessio Igor Bogani else 68162a26356SAlessio Igor Bogani export = export_from_sec(info, get_secindex(info, sym)); 6821da177e4SLinus Torvalds 6831da177e4SLinus Torvalds /* CRC'd symbol */ 684d62c4765SMasahiro Yamada if (strstarts(symname, "__crc_")) { 685d8c1eb86SNicholas Piggin is_crc = true; 6861da177e4SLinus Torvalds crc = (unsigned int) sym->st_value; 68756067812SArd Biesheuvel if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) { 68856067812SArd Biesheuvel unsigned int *crcp; 68956067812SArd Biesheuvel 69056067812SArd Biesheuvel /* symbol points to the CRC in the ELF object */ 69156067812SArd Biesheuvel crcp = (void *)info->hdr + sym->st_value + 69256067812SArd Biesheuvel info->sechdrs[sym->st_shndx].sh_offset - 69356067812SArd Biesheuvel (info->hdr->e_type != ET_REL ? 69456067812SArd Biesheuvel info->sechdrs[sym->st_shndx].sh_addr : 0); 69554a7151bSFredrik Noring crc = TO_NATIVE(*crcp); 69656067812SArd Biesheuvel } 697b2c5cdcfSMasahiro Yamada sym_update_crc(symname + strlen("__crc_"), mod, crc, 698bd5cbcedSRam Pai export); 6991da177e4SLinus Torvalds } 700b5064654SAndi Kleen 701b5064654SAndi Kleen switch (sym->st_shndx) { 702b5064654SAndi Kleen case SHN_COMMON: 703d62c4765SMasahiro Yamada if (strstarts(symname, "__gnu_lto_")) { 704ef178f92SAndi Kleen /* Should warn here, but modpost runs before the linker */ 705ef178f92SAndi Kleen } else 706b5064654SAndi Kleen warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name); 7071da177e4SLinus Torvalds break; 7081da177e4SLinus Torvalds case SHN_UNDEF: 7091da177e4SLinus Torvalds /* undefined symbol */ 7101da177e4SLinus Torvalds if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && 7111da177e4SLinus Torvalds ELF_ST_BIND(sym->st_info) != STB_WEAK) 7121da177e4SLinus Torvalds break; 7134d7365d6SSam Ravnborg if (ignore_undef_symbol(info, symname)) 7141da177e4SLinus Torvalds break; 7158d529014SBen Colline /* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */ 7168d529014SBen Colline #if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER) 7178d529014SBen Colline /* add compatibility with older glibc */ 7188d529014SBen Colline #ifndef STT_SPARC_REGISTER 7198d529014SBen Colline #define STT_SPARC_REGISTER STT_REGISTER 7208d529014SBen Colline #endif 7211da177e4SLinus Torvalds if (info->hdr->e_machine == EM_SPARC || 7221da177e4SLinus Torvalds info->hdr->e_machine == EM_SPARCV9) { 7231da177e4SLinus Torvalds /* Ignore register directives. */ 7248d529014SBen Colline if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER) 7251da177e4SLinus Torvalds break; 7267caaeabbSAl Viro if (symname[0] == '.') { 7271f3aa900SRandy Dunlap char *munged = NOFAIL(strdup(symname)); 7287caaeabbSAl Viro munged[0] = '_'; 7297caaeabbSAl Viro munged[1] = toupper(munged[1]); 7307caaeabbSAl Viro symname = munged; 7317caaeabbSAl Viro } 7321da177e4SLinus Torvalds } 7331da177e4SLinus Torvalds #endif 7341da177e4SLinus Torvalds 735d8c1eb86SNicholas Piggin if (is_crc) { 736d8c1eb86SNicholas Piggin const char *e = is_vmlinux(mod->name) ?"":".ko"; 737b2c5cdcfSMasahiro Yamada warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n", 738b2c5cdcfSMasahiro Yamada symname + strlen("__crc_"), mod->name, e); 739d8c1eb86SNicholas Piggin } 740b92021b0SRusty Russell mod->unres = alloc_symbol(symname, 7411da177e4SLinus Torvalds ELF_ST_BIND(sym->st_info) == STB_WEAK, 7421da177e4SLinus Torvalds mod->unres); 7431da177e4SLinus Torvalds break; 7441da177e4SLinus Torvalds default: 7451da177e4SLinus Torvalds /* All exported symbols */ 746d62c4765SMasahiro Yamada if (strstarts(symname, "__ksymtab_")) { 747cb9b55d2SMatthias Maennich name = symname + strlen("__ksymtab_"); 748cb9b55d2SMatthias Maennich namespace = sym_extract_namespace(&name); 749cb9b55d2SMatthias Maennich sym_add_exported(name, namespace, mod, export); 7501da177e4SLinus Torvalds } 751b2c5cdcfSMasahiro Yamada if (strcmp(symname, "init_module") == 0) 7521da177e4SLinus Torvalds mod->has_init = 1; 753b2c5cdcfSMasahiro Yamada if (strcmp(symname, "cleanup_module") == 0) 7541da177e4SLinus Torvalds mod->has_cleanup = 1; 7551da177e4SLinus Torvalds break; 7561da177e4SLinus Torvalds } 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds 7595c3ead8cSSam Ravnborg /** 7605c3ead8cSSam Ravnborg * Parse tag=value strings from .modinfo section 7615c3ead8cSSam Ravnborg **/ 7621da177e4SLinus Torvalds static char *next_string(char *string, unsigned long *secsize) 7631da177e4SLinus Torvalds { 7641da177e4SLinus Torvalds /* Skip non-zero chars */ 7651da177e4SLinus Torvalds while (string[0]) { 7661da177e4SLinus Torvalds string++; 7671da177e4SLinus Torvalds if ((*secsize)-- <= 1) 7681da177e4SLinus Torvalds return NULL; 7691da177e4SLinus Torvalds } 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds /* Skip any zero padding. */ 7721da177e4SLinus Torvalds while (!string[0]) { 7731da177e4SLinus Torvalds string++; 7741da177e4SLinus Torvalds if ((*secsize)-- <= 1) 7751da177e4SLinus Torvalds return NULL; 7761da177e4SLinus Torvalds } 7771da177e4SLinus Torvalds return string; 7781da177e4SLinus Torvalds } 7791da177e4SLinus Torvalds 780bca2cceeSMasahiro Yamada static char *get_next_modinfo(struct elf_info *info, const char *tag, 781bca2cceeSMasahiro Yamada char *prev) 7821da177e4SLinus Torvalds { 7831da177e4SLinus Torvalds char *p; 7841da177e4SLinus Torvalds unsigned int taglen = strlen(tag); 785bca2cceeSMasahiro Yamada char *modinfo = info->modinfo; 786bca2cceeSMasahiro Yamada unsigned long size = info->modinfo_len; 7871da177e4SLinus Torvalds 788bca2cceeSMasahiro Yamada if (prev) { 789bca2cceeSMasahiro Yamada size -= prev - modinfo; 790bca2cceeSMasahiro Yamada modinfo = next_string(prev, &size); 791b817f6feSSam Ravnborg } 792b817f6feSSam Ravnborg 7931da177e4SLinus Torvalds for (p = modinfo; p; p = next_string(p, &size)) { 7941da177e4SLinus Torvalds if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') 7951da177e4SLinus Torvalds return p + taglen + 1; 7961da177e4SLinus Torvalds } 7971da177e4SLinus Torvalds return NULL; 7981da177e4SLinus Torvalds } 7991da177e4SLinus Torvalds 800bca2cceeSMasahiro Yamada static char *get_modinfo(struct elf_info *info, const char *tag) 801b817f6feSSam Ravnborg 802b817f6feSSam Ravnborg { 803bca2cceeSMasahiro Yamada return get_next_modinfo(info, tag, NULL); 804b817f6feSSam Ravnborg } 805b817f6feSSam Ravnborg 80693684d3bSSam Ravnborg /** 8074c8fbca5SSam Ravnborg * Test if string s ends in string sub 8084c8fbca5SSam Ravnborg * return 0 if match 8094c8fbca5SSam Ravnborg **/ 8104c8fbca5SSam Ravnborg static int strrcmp(const char *s, const char *sub) 8114c8fbca5SSam Ravnborg { 8124c8fbca5SSam Ravnborg int slen, sublen; 8134c8fbca5SSam Ravnborg 8144c8fbca5SSam Ravnborg if (!s || !sub) 8154c8fbca5SSam Ravnborg return 1; 8164c8fbca5SSam Ravnborg 8174c8fbca5SSam Ravnborg slen = strlen(s); 8184c8fbca5SSam Ravnborg sublen = strlen(sub); 8194c8fbca5SSam Ravnborg 8204c8fbca5SSam Ravnborg if ((slen == 0) || (sublen == 0)) 8214c8fbca5SSam Ravnborg return 1; 8224c8fbca5SSam Ravnborg 8234c8fbca5SSam Ravnborg if (sublen > slen) 8244c8fbca5SSam Ravnborg return 1; 8254c8fbca5SSam Ravnborg 8264c8fbca5SSam Ravnborg return memcmp(s + slen - sublen, sub, sublen); 8274c8fbca5SSam Ravnborg } 8284c8fbca5SSam Ravnborg 829ff13f926SSam Ravnborg static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) 830ff13f926SSam Ravnborg { 83158fb0d4fSSam Ravnborg if (sym) 832ff13f926SSam Ravnborg return elf->strtab + sym->st_name; 83358fb0d4fSSam Ravnborg else 834f666751aSSam Ravnborg return "(unknown)"; 835ff13f926SSam Ravnborg } 836ff13f926SSam Ravnborg 83710668220SSam Ravnborg /* The pattern is an array of simple patterns. 83810668220SSam Ravnborg * "foo" will match an exact string equal to "foo" 8396c5bd235SSam Ravnborg * "*foo" will match a string that ends with "foo" 84010668220SSam Ravnborg * "foo*" will match a string that begins with "foo" 84109c20c03SPaul Gortmaker * "*foo*" will match a string that contains "foo" 84210668220SSam Ravnborg */ 8435c725138STrevor Keith static int match(const char *sym, const char * const pat[]) 84410668220SSam Ravnborg { 84510668220SSam Ravnborg const char *p; 84610668220SSam Ravnborg while (*pat) { 84710668220SSam Ravnborg p = *pat++; 84810668220SSam Ravnborg const char *endp = p + strlen(p) - 1; 84910668220SSam Ravnborg 85009c20c03SPaul Gortmaker /* "*foo*" */ 85109c20c03SPaul Gortmaker if (*p == '*' && *endp == '*') { 8526f02bdfcSDenis Efremov char *bare = NOFAIL(strndup(p + 1, strlen(p) - 2)); 8536f02bdfcSDenis Efremov char *here = strstr(sym, bare); 85409c20c03SPaul Gortmaker 85509c20c03SPaul Gortmaker free(bare); 85609c20c03SPaul Gortmaker if (here != NULL) 85709c20c03SPaul Gortmaker return 1; 85809c20c03SPaul Gortmaker } 8596c5bd235SSam Ravnborg /* "*foo" */ 86009c20c03SPaul Gortmaker else if (*p == '*') { 8616c5bd235SSam Ravnborg if (strrcmp(sym, p + 1) == 0) 8626c5bd235SSam Ravnborg return 1; 8636c5bd235SSam Ravnborg } 86410668220SSam Ravnborg /* "foo*" */ 8656c5bd235SSam Ravnborg else if (*endp == '*') { 86610668220SSam Ravnborg if (strncmp(sym, p, strlen(p) - 1) == 0) 86710668220SSam Ravnborg return 1; 86810668220SSam Ravnborg } 86910668220SSam Ravnborg /* no wildcards */ 87010668220SSam Ravnborg else { 87110668220SSam Ravnborg if (strcmp(p, sym) == 0) 87210668220SSam Ravnborg return 1; 87310668220SSam Ravnborg } 87410668220SSam Ravnborg } 87510668220SSam Ravnborg /* no match */ 87610668220SSam Ravnborg return 0; 87710668220SSam Ravnborg } 87810668220SSam Ravnborg 87910668220SSam Ravnborg /* sections that we do not want to do full section mismatch check on */ 8807a3ee753SMathias Krause static const char *const section_white_list[] = 8814391ed6aSSam Ravnborg { 8824391ed6aSSam Ravnborg ".comment*", 8834391ed6aSSam Ravnborg ".debug*", 8844d10c223SChen Gang ".cranges", /* sh64 */ 8851121584fSH.J. Lu ".zdebug*", /* Compressed debug sections. */ 886739d875dSDavid Howells ".GCC.command.line", /* record-gcc-switches */ 8874391ed6aSSam Ravnborg ".mdebug*", /* alpha, score, mips etc. */ 8884391ed6aSSam Ravnborg ".pdr", /* alpha, score, mips etc. */ 8894391ed6aSSam Ravnborg ".stab*", 8904391ed6aSSam Ravnborg ".note*", 8914391ed6aSSam Ravnborg ".got*", 8924391ed6aSSam Ravnborg ".toc*", 893af42e970SMax Filippov ".xt.prop", /* xtensa */ 894af42e970SMax Filippov ".xt.lit", /* xtensa */ 895f2e207f3SVineet Gupta ".arcextmap*", /* arc */ 896f2e207f3SVineet Gupta ".gnu.linkonce.arcext*", /* arc : modules */ 897d1189c63SNoam Camus ".cmem*", /* EZchip */ 898d1189c63SNoam Camus ".fmt_slot*", /* EZchip */ 899ef178f92SAndi Kleen ".gnu.lto*", 900e390f9a9SJosh Poimboeuf ".discard.*", 9014391ed6aSSam Ravnborg NULL 9024391ed6aSSam Ravnborg }; 90310668220SSam Ravnborg 904e241a630SSam Ravnborg /* 905b614a697SAnders Kaseorg * This is used to find sections missing the SHF_ALLOC flag. 906e241a630SSam Ravnborg * The cause of this is often a section specified in assembler 907b614a697SAnders Kaseorg * without "ax" / "aw". 908e241a630SSam Ravnborg */ 909b614a697SAnders Kaseorg static void check_section(const char *modname, struct elf_info *elf, 910b614a697SAnders Kaseorg Elf_Shdr *sechdr) 911e241a630SSam Ravnborg { 912b614a697SAnders Kaseorg const char *sec = sech_name(elf, sechdr); 913e241a630SSam Ravnborg 914b614a697SAnders Kaseorg if (sechdr->sh_type == SHT_PROGBITS && 915b614a697SAnders Kaseorg !(sechdr->sh_flags & SHF_ALLOC) && 916b614a697SAnders Kaseorg !match(sec, section_white_list)) { 917b614a697SAnders Kaseorg warn("%s (%s): unexpected non-allocatable section.\n" 918b614a697SAnders Kaseorg "Did you forget to use \"ax\"/\"aw\" in a .S file?\n" 919e241a630SSam Ravnborg "Note that for example <linux/init.h> contains\n" 920e241a630SSam Ravnborg "section definitions for use in .S files.\n\n", 921e241a630SSam Ravnborg modname, sec); 922e241a630SSam Ravnborg } 923e241a630SSam Ravnborg } 924e241a630SSam Ravnborg 925e241a630SSam Ravnborg 926e241a630SSam Ravnborg 927eb8f6890SSam Ravnborg #define ALL_INIT_DATA_SECTIONS \ 928a0d8f803SRasmus Villemoes ".init.setup", ".init.rodata", ".meminit.rodata", \ 929a0d8f803SRasmus Villemoes ".init.data", ".meminit.data" 930eb8f6890SSam Ravnborg #define ALL_EXIT_DATA_SECTIONS \ 931a0d8f803SRasmus Villemoes ".exit.data", ".memexit.data" 93210668220SSam Ravnborg 933eb8f6890SSam Ravnborg #define ALL_INIT_TEXT_SECTIONS \ 934a0d8f803SRasmus Villemoes ".init.text", ".meminit.text" 935eb8f6890SSam Ravnborg #define ALL_EXIT_TEXT_SECTIONS \ 936a0d8f803SRasmus Villemoes ".exit.text", ".memexit.text" 93710668220SSam Ravnborg 938bb15d8dbSSebastian Andrzej Siewior #define ALL_PCI_INIT_SECTIONS \ 939a0d8f803SRasmus Villemoes ".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \ 940a0d8f803SRasmus Villemoes ".pci_fixup_enable", ".pci_fixup_resume", \ 941a0d8f803SRasmus Villemoes ".pci_fixup_resume_early", ".pci_fixup_suspend" 942bb15d8dbSSebastian Andrzej Siewior 943e24f6628SPaul Gortmaker #define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS 944e24f6628SPaul Gortmaker #define ALL_XXXEXIT_SECTIONS MEM_EXIT_SECTIONS 9454a31a229SUwe Kleine-König 9464a31a229SUwe Kleine-König #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS 9474a31a229SUwe Kleine-König #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS 94810668220SSam Ravnborg 949a0d8f803SRasmus Villemoes #define DATA_SECTIONS ".data", ".data.rel" 950157d1972SQuentin Casasnovas #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ 9516727ad9eSChris Metcalf ".kprobes.text", ".cpuidle.text" 95252dc0595SQuentin Casasnovas #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ 953673c2c34SChris Metcalf ".fixup", ".entry.text", ".exception.text", ".text.*", \ 954673c2c34SChris Metcalf ".coldtext" 95510668220SSam Ravnborg 956fd6c3a8dSJan Beulich #define INIT_SECTIONS ".init.*" 957fd6c3a8dSJan Beulich #define MEM_INIT_SECTIONS ".meminit.*" 958eb8f6890SSam Ravnborg 959fd6c3a8dSJan Beulich #define EXIT_SECTIONS ".exit.*" 960fd6c3a8dSJan Beulich #define MEM_EXIT_SECTIONS ".memexit.*" 961eb8f6890SSam Ravnborg 96252dc0595SQuentin Casasnovas #define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \ 96352dc0595SQuentin Casasnovas TEXT_SECTIONS, OTHER_TEXT_SECTIONS 96452dc0595SQuentin Casasnovas 9656c5bd235SSam Ravnborg /* init data sections */ 9667a3ee753SMathias Krause static const char *const init_data_sections[] = 9677a3ee753SMathias Krause { ALL_INIT_DATA_SECTIONS, NULL }; 9686c5bd235SSam Ravnborg 9696c5bd235SSam Ravnborg /* all init sections */ 9707a3ee753SMathias Krause static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL }; 9716c5bd235SSam Ravnborg 9726c5bd235SSam Ravnborg /* All init and exit sections (code + data) */ 9737a3ee753SMathias Krause static const char *const init_exit_sections[] = 974eb8f6890SSam Ravnborg {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; 9756c5bd235SSam Ravnborg 9764a3893d0SPaul Gortmaker /* all text sections */ 9774a3893d0SPaul Gortmaker static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL }; 9784a3893d0SPaul Gortmaker 9796c5bd235SSam Ravnborg /* data section */ 9807a3ee753SMathias Krause static const char *const data_sections[] = { DATA_SECTIONS, NULL }; 9816c5bd235SSam Ravnborg 9826c5bd235SSam Ravnborg 9836c5bd235SSam Ravnborg /* symbols in .data that may refer to init/exit sections */ 984af92a82dSUwe Kleine-König #define DEFAULT_SYMBOL_WHITE_LIST \ 985af92a82dSUwe Kleine-König "*driver", \ 986af92a82dSUwe Kleine-König "*_template", /* scsi uses *_template a lot */ \ 987af92a82dSUwe Kleine-König "*_timer", /* arm uses ops structures named _timer a lot */ \ 988af92a82dSUwe Kleine-König "*_sht", /* scsi also used *_sht to some extent */ \ 989af92a82dSUwe Kleine-König "*_ops", \ 990af92a82dSUwe Kleine-König "*_probe", \ 991af92a82dSUwe Kleine-König "*_probe_one", \ 992af92a82dSUwe Kleine-König "*_console" 9936c5bd235SSam Ravnborg 9947a3ee753SMathias Krause static const char *const head_sections[] = { ".head.text*", NULL }; 9957a3ee753SMathias Krause static const char *const linker_symbols[] = 9966c5bd235SSam Ravnborg { "__init_begin", "_sinittext", "_einittext", NULL }; 9974a3893d0SPaul Gortmaker static const char *const optim_symbols[] = { "*.constprop.*", NULL }; 9986c5bd235SSam Ravnborg 999588ccd73SSam Ravnborg enum mismatch { 1000bbd3f4fbSUwe Kleine-König TEXT_TO_ANY_INIT, 1001bbd3f4fbSUwe Kleine-König DATA_TO_ANY_INIT, 1002bbd3f4fbSUwe Kleine-König TEXT_TO_ANY_EXIT, 1003bbd3f4fbSUwe Kleine-König DATA_TO_ANY_EXIT, 1004bbd3f4fbSUwe Kleine-König XXXINIT_TO_SOME_INIT, 1005bbd3f4fbSUwe Kleine-König XXXEXIT_TO_SOME_EXIT, 1006bbd3f4fbSUwe Kleine-König ANY_INIT_TO_ANY_EXIT, 1007bbd3f4fbSUwe Kleine-König ANY_EXIT_TO_ANY_INIT, 1008588ccd73SSam Ravnborg EXPORT_TO_INIT_EXIT, 100952dc0595SQuentin Casasnovas EXTABLE_TO_NON_TEXT, 1010588ccd73SSam Ravnborg }; 1011588ccd73SSam Ravnborg 1012e5d8f59aSQuentin Casasnovas /** 1013e5d8f59aSQuentin Casasnovas * Describe how to match sections on different criterias: 1014e5d8f59aSQuentin Casasnovas * 1015e5d8f59aSQuentin Casasnovas * @fromsec: Array of sections to be matched. 1016e5d8f59aSQuentin Casasnovas * 1017e5d8f59aSQuentin Casasnovas * @bad_tosec: Relocations applied to a section in @fromsec to a section in 1018e5d8f59aSQuentin Casasnovas * this array is forbidden (black-list). Can be empty. 1019e5d8f59aSQuentin Casasnovas * 1020e5d8f59aSQuentin Casasnovas * @good_tosec: Relocations applied to a section in @fromsec must be 1021e5d8f59aSQuentin Casasnovas * targetting sections in this array (white-list). Can be empty. 1022e5d8f59aSQuentin Casasnovas * 1023e5d8f59aSQuentin Casasnovas * @mismatch: Type of mismatch. 1024e5d8f59aSQuentin Casasnovas * 1025e5d8f59aSQuentin Casasnovas * @symbol_white_list: Do not match a relocation to a symbol in this list 1026e5d8f59aSQuentin Casasnovas * even if it is targetting a section in @bad_to_sec. 1027e5d8f59aSQuentin Casasnovas * 1028e5d8f59aSQuentin Casasnovas * @handler: Specific handler to call when a match is found. If NULL, 1029e5d8f59aSQuentin Casasnovas * default_mismatch_handler() will be called. 1030e5d8f59aSQuentin Casasnovas * 1031e5d8f59aSQuentin Casasnovas */ 103210668220SSam Ravnborg struct sectioncheck { 103310668220SSam Ravnborg const char *fromsec[20]; 1034050e57fdSQuentin Casasnovas const char *bad_tosec[20]; 1035050e57fdSQuentin Casasnovas const char *good_tosec[20]; 1036588ccd73SSam Ravnborg enum mismatch mismatch; 1037af92a82dSUwe Kleine-König const char *symbol_white_list[20]; 1038644e8f14SQuentin Casasnovas void (*handler)(const char *modname, struct elf_info *elf, 1039644e8f14SQuentin Casasnovas const struct sectioncheck* const mismatch, 1040644e8f14SQuentin Casasnovas Elf_Rela *r, Elf_Sym *sym, const char *fromsec); 1041644e8f14SQuentin Casasnovas 104210668220SSam Ravnborg }; 104310668220SSam Ravnborg 104452dc0595SQuentin Casasnovas static void extable_mismatch_handler(const char *modname, struct elf_info *elf, 104552dc0595SQuentin Casasnovas const struct sectioncheck* const mismatch, 104652dc0595SQuentin Casasnovas Elf_Rela *r, Elf_Sym *sym, 104752dc0595SQuentin Casasnovas const char *fromsec); 104852dc0595SQuentin Casasnovas 10497a3ee753SMathias Krause static const struct sectioncheck sectioncheck[] = { 105010668220SSam Ravnborg /* Do not reference init/exit code/data from 105110668220SSam Ravnborg * normal code and data 105210668220SSam Ravnborg */ 105310668220SSam Ravnborg { 1054588ccd73SSam Ravnborg .fromsec = { TEXT_SECTIONS, NULL }, 1055050e57fdSQuentin Casasnovas .bad_tosec = { ALL_INIT_SECTIONS, NULL }, 1056bbd3f4fbSUwe Kleine-König .mismatch = TEXT_TO_ANY_INIT, 1057af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1058588ccd73SSam Ravnborg }, 1059588ccd73SSam Ravnborg { 1060588ccd73SSam Ravnborg .fromsec = { DATA_SECTIONS, NULL }, 1061050e57fdSQuentin Casasnovas .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL }, 1062bbd3f4fbSUwe Kleine-König .mismatch = DATA_TO_ANY_INIT, 1063af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1064588ccd73SSam Ravnborg }, 1065588ccd73SSam Ravnborg { 10660db25245SUwe Kleine-König .fromsec = { DATA_SECTIONS, NULL }, 1067050e57fdSQuentin Casasnovas .bad_tosec = { INIT_SECTIONS, NULL }, 10680db25245SUwe Kleine-König .mismatch = DATA_TO_ANY_INIT, 10690db25245SUwe Kleine-König .symbol_white_list = { 10700db25245SUwe Kleine-König "*_template", "*_timer", "*_sht", "*_ops", 10710db25245SUwe Kleine-König "*_probe", "*_probe_one", "*_console", NULL 10720db25245SUwe Kleine-König }, 10730db25245SUwe Kleine-König }, 10740db25245SUwe Kleine-König { 1075588ccd73SSam Ravnborg .fromsec = { TEXT_SECTIONS, NULL }, 1076050e57fdSQuentin Casasnovas .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, 1077bbd3f4fbSUwe Kleine-König .mismatch = TEXT_TO_ANY_EXIT, 1078af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1079588ccd73SSam Ravnborg }, 1080588ccd73SSam Ravnborg { 1081588ccd73SSam Ravnborg .fromsec = { DATA_SECTIONS, NULL }, 1082050e57fdSQuentin Casasnovas .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, 1083bbd3f4fbSUwe Kleine-König .mismatch = DATA_TO_ANY_EXIT, 1084af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1085eb8f6890SSam Ravnborg }, 1086e24f6628SPaul Gortmaker /* Do not reference init code/data from meminit code/data */ 1087eb8f6890SSam Ravnborg { 10884a31a229SUwe Kleine-König .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, 1089050e57fdSQuentin Casasnovas .bad_tosec = { INIT_SECTIONS, NULL }, 1090bbd3f4fbSUwe Kleine-König .mismatch = XXXINIT_TO_SOME_INIT, 1091af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 1092eb8f6890SSam Ravnborg }, 1093e24f6628SPaul Gortmaker /* Do not reference exit code/data from memexit code/data */ 1094eb8f6890SSam Ravnborg { 10954a31a229SUwe Kleine-König .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, 1096050e57fdSQuentin Casasnovas .bad_tosec = { EXIT_SECTIONS, NULL }, 1097bbd3f4fbSUwe Kleine-König .mismatch = XXXEXIT_TO_SOME_EXIT, 1098af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 109910668220SSam Ravnborg }, 110010668220SSam Ravnborg /* Do not use exit code/data from init code */ 110110668220SSam Ravnborg { 1102eb8f6890SSam Ravnborg .fromsec = { ALL_INIT_SECTIONS, NULL }, 1103050e57fdSQuentin Casasnovas .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, 1104bbd3f4fbSUwe Kleine-König .mismatch = ANY_INIT_TO_ANY_EXIT, 1105af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 110610668220SSam Ravnborg }, 110710668220SSam Ravnborg /* Do not use init code/data from exit code */ 110810668220SSam Ravnborg { 1109eb8f6890SSam Ravnborg .fromsec = { ALL_EXIT_SECTIONS, NULL }, 1110050e57fdSQuentin Casasnovas .bad_tosec = { ALL_INIT_SECTIONS, NULL }, 1111bbd3f4fbSUwe Kleine-König .mismatch = ANY_EXIT_TO_ANY_INIT, 1112af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 111310668220SSam Ravnborg }, 1114bb15d8dbSSebastian Andrzej Siewior { 1115bb15d8dbSSebastian Andrzej Siewior .fromsec = { ALL_PCI_INIT_SECTIONS, NULL }, 1116050e57fdSQuentin Casasnovas .bad_tosec = { INIT_SECTIONS, NULL }, 1117bb15d8dbSSebastian Andrzej Siewior .mismatch = ANY_INIT_TO_ANY_EXIT, 1118bb15d8dbSSebastian Andrzej Siewior .symbol_white_list = { NULL }, 1119bb15d8dbSSebastian Andrzej Siewior }, 112010668220SSam Ravnborg /* Do not export init/exit functions or data */ 112110668220SSam Ravnborg { 112210668220SSam Ravnborg .fromsec = { "__ksymtab*", NULL }, 1123050e57fdSQuentin Casasnovas .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, 1124af92a82dSUwe Kleine-König .mismatch = EXPORT_TO_INIT_EXIT, 1125af92a82dSUwe Kleine-König .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, 112652dc0595SQuentin Casasnovas }, 112752dc0595SQuentin Casasnovas { 112852dc0595SQuentin Casasnovas .fromsec = { "__ex_table", NULL }, 112952dc0595SQuentin Casasnovas /* If you're adding any new black-listed sections in here, consider 113052dc0595SQuentin Casasnovas * adding a special 'printer' for them in scripts/check_extable. 113152dc0595SQuentin Casasnovas */ 113252dc0595SQuentin Casasnovas .bad_tosec = { ".altinstr_replacement", NULL }, 113352dc0595SQuentin Casasnovas .good_tosec = {ALL_TEXT_SECTIONS , NULL}, 113452dc0595SQuentin Casasnovas .mismatch = EXTABLE_TO_NON_TEXT, 113552dc0595SQuentin Casasnovas .handler = extable_mismatch_handler, 113610668220SSam Ravnborg } 113710668220SSam Ravnborg }; 113810668220SSam Ravnborg 11390d2a636eSUwe Kleine-König static const struct sectioncheck *section_mismatch( 11400d2a636eSUwe Kleine-König const char *fromsec, const char *tosec) 114110668220SSam Ravnborg { 114210668220SSam Ravnborg int i; 114310668220SSam Ravnborg int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); 114410668220SSam Ravnborg const struct sectioncheck *check = §ioncheck[0]; 114510668220SSam Ravnborg 1146c5c3439aSQuentin Casasnovas /* 1147c5c3439aSQuentin Casasnovas * The target section could be the SHT_NUL section when we're 1148c5c3439aSQuentin Casasnovas * handling relocations to un-resolved symbols, trying to match it 1149739d875dSDavid Howells * doesn't make much sense and causes build failures on parisc 1150739d875dSDavid Howells * architectures. 1151c5c3439aSQuentin Casasnovas */ 1152c5c3439aSQuentin Casasnovas if (*tosec == '\0') 1153c5c3439aSQuentin Casasnovas return NULL; 1154c5c3439aSQuentin Casasnovas 115510668220SSam Ravnborg for (i = 0; i < elems; i++) { 1156050e57fdSQuentin Casasnovas if (match(fromsec, check->fromsec)) { 1157050e57fdSQuentin Casasnovas if (check->bad_tosec[0] && match(tosec, check->bad_tosec)) 11580d2a636eSUwe Kleine-König return check; 1159050e57fdSQuentin Casasnovas if (check->good_tosec[0] && !match(tosec, check->good_tosec)) 1160050e57fdSQuentin Casasnovas return check; 1161050e57fdSQuentin Casasnovas } 116210668220SSam Ravnborg check++; 116310668220SSam Ravnborg } 11640d2a636eSUwe Kleine-König return NULL; 116510668220SSam Ravnborg } 116610668220SSam Ravnborg 11674c8fbca5SSam Ravnborg /** 11684c8fbca5SSam Ravnborg * Whitelist to allow certain references to pass with no warning. 11690e0d314eSSam Ravnborg * 11704c8fbca5SSam Ravnborg * Pattern 1: 11714c8fbca5SSam Ravnborg * If a module parameter is declared __initdata and permissions=0 11724c8fbca5SSam Ravnborg * then this is legal despite the warning generated. 11734c8fbca5SSam Ravnborg * We cannot see value of permissions here, so just ignore 11744c8fbca5SSam Ravnborg * this pattern. 11754c8fbca5SSam Ravnborg * The pattern is identified by: 11764c8fbca5SSam Ravnborg * tosec = .init.data 11779209aed0SSam Ravnborg * fromsec = .data* 11784c8fbca5SSam Ravnborg * atsym =__param* 11794c8fbca5SSam Ravnborg * 11806a841528SRusty Russell * Pattern 1a: 11816a841528SRusty Russell * module_param_call() ops can refer to __init set function if permissions=0 11826a841528SRusty Russell * The pattern is identified by: 11836a841528SRusty Russell * tosec = .init.text 11846a841528SRusty Russell * fromsec = .data* 11856a841528SRusty Russell * atsym = __param_ops_* 11866a841528SRusty Russell * 11874c8fbca5SSam Ravnborg * Pattern 2: 118872ee59b5SRandy Dunlap * Many drivers utilise a *driver container with references to 11894c8fbca5SSam Ravnborg * add, remove, probe functions etc. 11904c8fbca5SSam Ravnborg * the pattern is identified by: 119183cda2bbSSam Ravnborg * tosec = init or exit section 119283cda2bbSSam Ravnborg * fromsec = data section 1193df578e7dSSam Ravnborg * atsym = *driver, *_template, *_sht, *_ops, *_probe, 1194df578e7dSSam Ravnborg * *probe_one, *_console, *_timer 1195ee6a8545SVivek Goyal * 1196ee6a8545SVivek Goyal * Pattern 3: 1197c993971fSSam Ravnborg * Whitelist all references from .head.text to any init section 11989bf8cb9bSSam Ravnborg * 11991d8af559SSam Ravnborg * Pattern 4: 1200ee6a8545SVivek Goyal * Some symbols belong to init section but still it is ok to reference 1201ee6a8545SVivek Goyal * these from non-init sections as these symbols don't have any memory 1202ee6a8545SVivek Goyal * allocated for them and symbol address and value are same. So even 1203ee6a8545SVivek Goyal * if init section is freed, its ok to reference those symbols. 1204ee6a8545SVivek Goyal * For ex. symbols marking the init section boundaries. 1205ee6a8545SVivek Goyal * This pattern is identified by 1206ee6a8545SVivek Goyal * refsymname = __init_begin, _sinittext, _einittext 12079bf8cb9bSSam Ravnborg * 12084a3893d0SPaul Gortmaker * Pattern 5: 12094a3893d0SPaul Gortmaker * GCC may optimize static inlines when fed constant arg(s) resulting 12104a3893d0SPaul Gortmaker * in functions like cpumask_empty() -- generating an associated symbol 12114a3893d0SPaul Gortmaker * cpumask_empty.constprop.3 that appears in the audit. If the const that 12124a3893d0SPaul Gortmaker * is passed in comes from __init, like say nmi_ipi_mask, we get a 12134a3893d0SPaul Gortmaker * meaningless section warning. May need to add isra symbols too... 12144a3893d0SPaul Gortmaker * This pattern is identified by 12154a3893d0SPaul Gortmaker * tosec = init section 12164a3893d0SPaul Gortmaker * fromsec = text section 12174a3893d0SPaul Gortmaker * refsymname = *.constprop.* 12184a3893d0SPaul Gortmaker * 1219a4d26f1aSPaul Walmsley * Pattern 6: 1220a4d26f1aSPaul Walmsley * Hide section mismatch warnings for ELF local symbols. The goal 1221a4d26f1aSPaul Walmsley * is to eliminate false positive modpost warnings caused by 1222a4d26f1aSPaul Walmsley * compiler-generated ELF local symbol names such as ".LANCHOR1". 1223a4d26f1aSPaul Walmsley * Autogenerated symbol names bypass modpost's "Pattern 2" 1224a4d26f1aSPaul Walmsley * whitelisting, which relies on pattern-matching against symbol 1225a4d26f1aSPaul Walmsley * names to work. (One situation where gcc can autogenerate ELF 1226a4d26f1aSPaul Walmsley * local symbols is when "-fsection-anchors" is used.) 12274c8fbca5SSam Ravnborg **/ 1228af92a82dSUwe Kleine-König static int secref_whitelist(const struct sectioncheck *mismatch, 1229af92a82dSUwe Kleine-König const char *fromsec, const char *fromsym, 123058fb0d4fSSam Ravnborg const char *tosec, const char *tosym) 12314c8fbca5SSam Ravnborg { 12324c8fbca5SSam Ravnborg /* Check for pattern 1 */ 12336c5bd235SSam Ravnborg if (match(tosec, init_data_sections) && 12346c5bd235SSam Ravnborg match(fromsec, data_sections) && 1235d62c4765SMasahiro Yamada strstarts(fromsym, "__param")) 123658fb0d4fSSam Ravnborg return 0; 12374c8fbca5SSam Ravnborg 12386a841528SRusty Russell /* Check for pattern 1a */ 12396a841528SRusty Russell if (strcmp(tosec, ".init.text") == 0 && 12406a841528SRusty Russell match(fromsec, data_sections) && 1241d62c4765SMasahiro Yamada strstarts(fromsym, "__param_ops_")) 12426a841528SRusty Russell return 0; 12436a841528SRusty Russell 12444c8fbca5SSam Ravnborg /* Check for pattern 2 */ 12456c5bd235SSam Ravnborg if (match(tosec, init_exit_sections) && 12466c5bd235SSam Ravnborg match(fromsec, data_sections) && 1247af92a82dSUwe Kleine-König match(fromsym, mismatch->symbol_white_list)) 124858fb0d4fSSam Ravnborg return 0; 12494c8fbca5SSam Ravnborg 12509bf8cb9bSSam Ravnborg /* Check for pattern 3 */ 12516c5bd235SSam Ravnborg if (match(fromsec, head_sections) && 12526c5bd235SSam Ravnborg match(tosec, init_sections)) 125358fb0d4fSSam Ravnborg return 0; 1254f8657e1bSVivek Goyal 12551d8af559SSam Ravnborg /* Check for pattern 4 */ 125658fb0d4fSSam Ravnborg if (match(tosym, linker_symbols)) 125793659af1SSam Ravnborg return 0; 125858fb0d4fSSam Ravnborg 12594a3893d0SPaul Gortmaker /* Check for pattern 5 */ 12604a3893d0SPaul Gortmaker if (match(fromsec, text_sections) && 12614a3893d0SPaul Gortmaker match(tosec, init_sections) && 12624a3893d0SPaul Gortmaker match(fromsym, optim_symbols)) 12634a3893d0SPaul Gortmaker return 0; 12644a3893d0SPaul Gortmaker 1265a4d26f1aSPaul Walmsley /* Check for pattern 6 */ 1266a4d26f1aSPaul Walmsley if (strstarts(fromsym, ".L")) 1267a4d26f1aSPaul Walmsley return 0; 1268a4d26f1aSPaul Walmsley 126958fb0d4fSSam Ravnborg return 1; 12704c8fbca5SSam Ravnborg } 12714c8fbca5SSam Ravnborg 12725818c683SSami Tolvanen static inline int is_arm_mapping_symbol(const char *str) 12735818c683SSami Tolvanen { 12745818c683SSami Tolvanen return str[0] == '$' && strchr("axtd", str[1]) 12755818c683SSami Tolvanen && (str[2] == '\0' || str[2] == '.'); 12765818c683SSami Tolvanen } 12775818c683SSami Tolvanen 12785818c683SSami Tolvanen /* 12795818c683SSami Tolvanen * If there's no name there, ignore it; likewise, ignore it if it's 12805818c683SSami Tolvanen * one of the magic symbols emitted used by current ARM tools. 12815818c683SSami Tolvanen * 12825818c683SSami Tolvanen * Otherwise if find_symbols_between() returns those symbols, they'll 12835818c683SSami Tolvanen * fail the whitelist tests and cause lots of false alarms ... fixable 12845818c683SSami Tolvanen * only by merging __exit and __init sections into __text, bloating 12855818c683SSami Tolvanen * the kernel (which is especially evil on embedded platforms). 12865818c683SSami Tolvanen */ 12875818c683SSami Tolvanen static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) 12885818c683SSami Tolvanen { 12895818c683SSami Tolvanen const char *name = elf->strtab + sym->st_name; 12905818c683SSami Tolvanen 12915818c683SSami Tolvanen if (!name || !strlen(name)) 12925818c683SSami Tolvanen return 0; 12935818c683SSami Tolvanen return !is_arm_mapping_symbol(name); 12945818c683SSami Tolvanen } 12955818c683SSami Tolvanen 12964c8fbca5SSam Ravnborg /** 129793684d3bSSam Ravnborg * Find symbol based on relocation record info. 129893684d3bSSam Ravnborg * In some cases the symbol supplied is a valid symbol so 129993684d3bSSam Ravnborg * return refsym. If st_name != 0 we assume this is a valid symbol. 130093684d3bSSam Ravnborg * In other cases the symbol needs to be looked up in the symbol table 130193684d3bSSam Ravnborg * based on section and address. 130293684d3bSSam Ravnborg * **/ 13039ad21c3fSSam Ravnborg static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, 130493684d3bSSam Ravnborg Elf_Sym *relsym) 130593684d3bSSam Ravnborg { 130693684d3bSSam Ravnborg Elf_Sym *sym; 13079ad21c3fSSam Ravnborg Elf_Sym *near = NULL; 13089ad21c3fSSam Ravnborg Elf64_Sword distance = 20; 13099ad21c3fSSam Ravnborg Elf64_Sword d; 13101ce53adfSDenys Vlasenko unsigned int relsym_secindex; 131193684d3bSSam Ravnborg 131293684d3bSSam Ravnborg if (relsym->st_name != 0) 131393684d3bSSam Ravnborg return relsym; 13141ce53adfSDenys Vlasenko 13151ce53adfSDenys Vlasenko relsym_secindex = get_secindex(elf, relsym); 131693684d3bSSam Ravnborg for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { 13171ce53adfSDenys Vlasenko if (get_secindex(elf, sym) != relsym_secindex) 131893684d3bSSam Ravnborg continue; 1319ae4ac123SAtsushi Nemoto if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) 1320ae4ac123SAtsushi Nemoto continue; 13215818c683SSami Tolvanen if (!is_valid_name(elf, sym)) 13225818c683SSami Tolvanen continue; 132393684d3bSSam Ravnborg if (sym->st_value == addr) 132493684d3bSSam Ravnborg return sym; 13259ad21c3fSSam Ravnborg /* Find a symbol nearby - addr are maybe negative */ 13269ad21c3fSSam Ravnborg d = sym->st_value - addr; 13279ad21c3fSSam Ravnborg if (d < 0) 13289ad21c3fSSam Ravnborg d = addr - sym->st_value; 13299ad21c3fSSam Ravnborg if (d < distance) { 13309ad21c3fSSam Ravnborg distance = d; 13319ad21c3fSSam Ravnborg near = sym; 133293684d3bSSam Ravnborg } 13339ad21c3fSSam Ravnborg } 13349ad21c3fSSam Ravnborg /* We need a close match */ 13359ad21c3fSSam Ravnborg if (distance < 20) 13369ad21c3fSSam Ravnborg return near; 13379ad21c3fSSam Ravnborg else 133893684d3bSSam Ravnborg return NULL; 133993684d3bSSam Ravnborg } 134093684d3bSSam Ravnborg 1341b39927cfSSam Ravnborg /* 134243c74d17SSam Ravnborg * Find symbols before or equal addr and after addr - in the section sec. 134343c74d17SSam Ravnborg * If we find two symbols with equal offset prefer one with a valid name. 134443c74d17SSam Ravnborg * The ELF format may have a better way to detect what type of symbol 134543c74d17SSam Ravnborg * it is, but this works for now. 1346b39927cfSSam Ravnborg **/ 1347157c23c8SSam Ravnborg static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, 1348157c23c8SSam Ravnborg const char *sec) 1349b39927cfSSam Ravnborg { 1350b39927cfSSam Ravnborg Elf_Sym *sym; 1351157c23c8SSam Ravnborg Elf_Sym *near = NULL; 1352157c23c8SSam Ravnborg Elf_Addr distance = ~0; 1353b39927cfSSam Ravnborg 1354b39927cfSSam Ravnborg for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { 1355b39927cfSSam Ravnborg const char *symsec; 1356b39927cfSSam Ravnborg 13571ce53adfSDenys Vlasenko if (is_shndx_special(sym->st_shndx)) 1358b39927cfSSam Ravnborg continue; 13591ce53adfSDenys Vlasenko symsec = sec_name(elf, get_secindex(elf, sym)); 1360b39927cfSSam Ravnborg if (strcmp(symsec, sec) != 0) 1361b39927cfSSam Ravnborg continue; 1362da68d61fSDavid Brownell if (!is_valid_name(elf, sym)) 1363da68d61fSDavid Brownell continue; 1364b39927cfSSam Ravnborg if (sym->st_value <= addr) { 1365157c23c8SSam Ravnborg if ((addr - sym->st_value) < distance) { 1366157c23c8SSam Ravnborg distance = addr - sym->st_value; 1367157c23c8SSam Ravnborg near = sym; 1368157c23c8SSam Ravnborg } else if ((addr - sym->st_value) == distance) { 1369157c23c8SSam Ravnborg near = sym; 137043c74d17SSam Ravnborg } 1371b39927cfSSam Ravnborg } 1372b39927cfSSam Ravnborg } 1373157c23c8SSam Ravnborg return near; 1374157c23c8SSam Ravnborg } 1375b39927cfSSam Ravnborg 137658fb0d4fSSam Ravnborg /* 1377588ccd73SSam Ravnborg * Convert a section name to the function/data attribute 1378588ccd73SSam Ravnborg * .init.text => __init 1379588ccd73SSam Ravnborg * .memexitconst => __memconst 1380588ccd73SSam Ravnborg * etc. 1381cbcf14a9SAndy Shevchenko * 1382cbcf14a9SAndy Shevchenko * The memory of returned value has been allocated on a heap. The user of this 1383cbcf14a9SAndy Shevchenko * method should free it after usage. 1384588ccd73SSam Ravnborg */ 1385588ccd73SSam Ravnborg static char *sec2annotation(const char *s) 1386588ccd73SSam Ravnborg { 1387588ccd73SSam Ravnborg if (match(s, init_exit_sections)) { 13881f3aa900SRandy Dunlap char *p = NOFAIL(malloc(20)); 1389588ccd73SSam Ravnborg char *r = p; 1390588ccd73SSam Ravnborg 1391588ccd73SSam Ravnborg *p++ = '_'; 1392588ccd73SSam Ravnborg *p++ = '_'; 1393588ccd73SSam Ravnborg if (*s == '.') 1394588ccd73SSam Ravnborg s++; 1395588ccd73SSam Ravnborg while (*s && *s != '.') 1396588ccd73SSam Ravnborg *p++ = *s++; 1397588ccd73SSam Ravnborg *p = '\0'; 1398588ccd73SSam Ravnborg if (*s == '.') 1399588ccd73SSam Ravnborg s++; 1400588ccd73SSam Ravnborg if (strstr(s, "rodata") != NULL) 1401588ccd73SSam Ravnborg strcat(p, "const "); 1402588ccd73SSam Ravnborg else if (strstr(s, "data") != NULL) 1403588ccd73SSam Ravnborg strcat(p, "data "); 1404588ccd73SSam Ravnborg else 1405588ccd73SSam Ravnborg strcat(p, " "); 1406cbcf14a9SAndy Shevchenko return r; 1407588ccd73SSam Ravnborg } else { 14081f3aa900SRandy Dunlap return NOFAIL(strdup("")); 1409588ccd73SSam Ravnborg } 1410588ccd73SSam Ravnborg } 1411588ccd73SSam Ravnborg 1412588ccd73SSam Ravnborg static int is_function(Elf_Sym *sym) 1413588ccd73SSam Ravnborg { 1414588ccd73SSam Ravnborg if (sym) 1415588ccd73SSam Ravnborg return ELF_ST_TYPE(sym->st_info) == STT_FUNC; 1416588ccd73SSam Ravnborg else 1417f666751aSSam Ravnborg return -1; 1418588ccd73SSam Ravnborg } 1419588ccd73SSam Ravnborg 142000759c0eSRandy Dunlap static void print_section_list(const char * const list[20]) 142100759c0eSRandy Dunlap { 142200759c0eSRandy Dunlap const char *const *s = list; 142300759c0eSRandy Dunlap 142400759c0eSRandy Dunlap while (*s) { 142500759c0eSRandy Dunlap fprintf(stderr, "%s", *s); 142600759c0eSRandy Dunlap s++; 142700759c0eSRandy Dunlap if (*s) 142800759c0eSRandy Dunlap fprintf(stderr, ", "); 142900759c0eSRandy Dunlap } 143000759c0eSRandy Dunlap fprintf(stderr, "\n"); 143100759c0eSRandy Dunlap } 143200759c0eSRandy Dunlap 1433356ad538SQuentin Casasnovas static inline void get_pretty_name(int is_func, const char** name, const char** name_p) 1434356ad538SQuentin Casasnovas { 1435356ad538SQuentin Casasnovas switch (is_func) { 1436356ad538SQuentin Casasnovas case 0: *name = "variable"; *name_p = ""; break; 1437356ad538SQuentin Casasnovas case 1: *name = "function"; *name_p = "()"; break; 1438356ad538SQuentin Casasnovas default: *name = "(unknown reference)"; *name_p = ""; break; 1439356ad538SQuentin Casasnovas } 1440356ad538SQuentin Casasnovas } 1441356ad538SQuentin Casasnovas 1442588ccd73SSam Ravnborg /* 1443b39927cfSSam Ravnborg * Print a warning about a section mismatch. 1444b39927cfSSam Ravnborg * Try to find symbols near it so user can find it. 14454c8fbca5SSam Ravnborg * Check whitelist before warning - it may be a false positive. 144658fb0d4fSSam Ravnborg */ 14470d2a636eSUwe Kleine-König static void report_sec_mismatch(const char *modname, 14480d2a636eSUwe Kleine-König const struct sectioncheck *mismatch, 144958fb0d4fSSam Ravnborg const char *fromsec, 145058fb0d4fSSam Ravnborg unsigned long long fromaddr, 145158fb0d4fSSam Ravnborg const char *fromsym, 1452588ccd73SSam Ravnborg int from_is_func, 1453588ccd73SSam Ravnborg const char *tosec, const char *tosym, 1454588ccd73SSam Ravnborg int to_is_func) 1455b39927cfSSam Ravnborg { 1456588ccd73SSam Ravnborg const char *from, *from_p; 1457588ccd73SSam Ravnborg const char *to, *to_p; 145837ed19d5SAlexey Fomenko char *prl_from; 145937ed19d5SAlexey Fomenko char *prl_to; 1460f666751aSSam Ravnborg 1461e5f95c8bSSam Ravnborg sec_mismatch_count++; 1462e5f95c8bSSam Ravnborg 1463356ad538SQuentin Casasnovas get_pretty_name(from_is_func, &from, &from_p); 1464356ad538SQuentin Casasnovas get_pretty_name(to_is_func, &to, &to_p); 1465356ad538SQuentin Casasnovas 14667c0ac495SGeert Uytterhoeven warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s " 14677c0ac495SGeert Uytterhoeven "to the %s %s:%s%s\n", 14687c0ac495SGeert Uytterhoeven modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec, 14697c0ac495SGeert Uytterhoeven tosym, to_p); 1470588ccd73SSam Ravnborg 14710d2a636eSUwe Kleine-König switch (mismatch->mismatch) { 1472bbd3f4fbSUwe Kleine-König case TEXT_TO_ANY_INIT: 147337ed19d5SAlexey Fomenko prl_from = sec2annotation(fromsec); 147437ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1475588ccd73SSam Ravnborg fprintf(stderr, 1476588ccd73SSam Ravnborg "The function %s%s() references\n" 1477588ccd73SSam Ravnborg "the %s %s%s%s.\n" 1478588ccd73SSam Ravnborg "This is often because %s lacks a %s\n" 1479588ccd73SSam Ravnborg "annotation or the annotation of %s is wrong.\n", 148037ed19d5SAlexey Fomenko prl_from, fromsym, 148137ed19d5SAlexey Fomenko to, prl_to, tosym, to_p, 148237ed19d5SAlexey Fomenko fromsym, prl_to, tosym); 148337ed19d5SAlexey Fomenko free(prl_from); 148437ed19d5SAlexey Fomenko free(prl_to); 1485588ccd73SSam Ravnborg break; 1486bbd3f4fbSUwe Kleine-König case DATA_TO_ANY_INIT: { 148737ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1488588ccd73SSam Ravnborg fprintf(stderr, 1489588ccd73SSam Ravnborg "The variable %s references\n" 1490588ccd73SSam Ravnborg "the %s %s%s%s\n" 1491588ccd73SSam Ravnborg "If the reference is valid then annotate the\n" 14928b8b76c0SSam Ravnborg "variable with __init* or __refdata (see linux/init.h) " 1493588ccd73SSam Ravnborg "or name the variable:\n", 149437ed19d5SAlexey Fomenko fromsym, to, prl_to, tosym, to_p); 149500759c0eSRandy Dunlap print_section_list(mismatch->symbol_white_list); 149637ed19d5SAlexey Fomenko free(prl_to); 1497588ccd73SSam Ravnborg break; 149858fb0d4fSSam Ravnborg } 1499bbd3f4fbSUwe Kleine-König case TEXT_TO_ANY_EXIT: 150037ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1501588ccd73SSam Ravnborg fprintf(stderr, 1502588ccd73SSam Ravnborg "The function %s() references a %s in an exit section.\n" 1503588ccd73SSam Ravnborg "Often the %s %s%s has valid usage outside the exit section\n" 1504588ccd73SSam Ravnborg "and the fix is to remove the %sannotation of %s.\n", 150537ed19d5SAlexey Fomenko fromsym, to, to, tosym, to_p, prl_to, tosym); 150637ed19d5SAlexey Fomenko free(prl_to); 1507588ccd73SSam Ravnborg break; 1508bbd3f4fbSUwe Kleine-König case DATA_TO_ANY_EXIT: { 150937ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1510588ccd73SSam Ravnborg fprintf(stderr, 1511588ccd73SSam Ravnborg "The variable %s references\n" 1512588ccd73SSam Ravnborg "the %s %s%s%s\n" 1513588ccd73SSam Ravnborg "If the reference is valid then annotate the\n" 1514588ccd73SSam Ravnborg "variable with __exit* (see linux/init.h) or " 1515588ccd73SSam Ravnborg "name the variable:\n", 151637ed19d5SAlexey Fomenko fromsym, to, prl_to, tosym, to_p); 151700759c0eSRandy Dunlap print_section_list(mismatch->symbol_white_list); 151837ed19d5SAlexey Fomenko free(prl_to); 1519588ccd73SSam Ravnborg break; 1520588ccd73SSam Ravnborg } 1521bbd3f4fbSUwe Kleine-König case XXXINIT_TO_SOME_INIT: 1522bbd3f4fbSUwe Kleine-König case XXXEXIT_TO_SOME_EXIT: 152337ed19d5SAlexey Fomenko prl_from = sec2annotation(fromsec); 152437ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1525588ccd73SSam Ravnborg fprintf(stderr, 1526588ccd73SSam Ravnborg "The %s %s%s%s references\n" 1527588ccd73SSam Ravnborg "a %s %s%s%s.\n" 1528588ccd73SSam Ravnborg "If %s is only used by %s then\n" 1529588ccd73SSam Ravnborg "annotate %s with a matching annotation.\n", 153037ed19d5SAlexey Fomenko from, prl_from, fromsym, from_p, 153137ed19d5SAlexey Fomenko to, prl_to, tosym, to_p, 1532b1d2675aSGeert Uytterhoeven tosym, fromsym, tosym); 153337ed19d5SAlexey Fomenko free(prl_from); 153437ed19d5SAlexey Fomenko free(prl_to); 1535588ccd73SSam Ravnborg break; 1536bbd3f4fbSUwe Kleine-König case ANY_INIT_TO_ANY_EXIT: 153737ed19d5SAlexey Fomenko prl_from = sec2annotation(fromsec); 153837ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1539588ccd73SSam Ravnborg fprintf(stderr, 1540588ccd73SSam Ravnborg "The %s %s%s%s references\n" 1541588ccd73SSam Ravnborg "a %s %s%s%s.\n" 1542588ccd73SSam Ravnborg "This is often seen when error handling " 1543588ccd73SSam Ravnborg "in the init function\n" 1544588ccd73SSam Ravnborg "uses functionality in the exit path.\n" 1545588ccd73SSam Ravnborg "The fix is often to remove the %sannotation of\n" 1546588ccd73SSam Ravnborg "%s%s so it may be used outside an exit section.\n", 154737ed19d5SAlexey Fomenko from, prl_from, fromsym, from_p, 154837ed19d5SAlexey Fomenko to, prl_to, tosym, to_p, 15495003bab8SAndrew Morton prl_to, tosym, to_p); 155037ed19d5SAlexey Fomenko free(prl_from); 155137ed19d5SAlexey Fomenko free(prl_to); 1552588ccd73SSam Ravnborg break; 1553bbd3f4fbSUwe Kleine-König case ANY_EXIT_TO_ANY_INIT: 155437ed19d5SAlexey Fomenko prl_from = sec2annotation(fromsec); 155537ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1556588ccd73SSam Ravnborg fprintf(stderr, 1557588ccd73SSam Ravnborg "The %s %s%s%s references\n" 1558588ccd73SSam Ravnborg "a %s %s%s%s.\n" 1559588ccd73SSam Ravnborg "This is often seen when error handling " 1560588ccd73SSam Ravnborg "in the exit function\n" 1561588ccd73SSam Ravnborg "uses functionality in the init path.\n" 1562588ccd73SSam Ravnborg "The fix is often to remove the %sannotation of\n" 1563588ccd73SSam Ravnborg "%s%s so it may be used outside an init section.\n", 156437ed19d5SAlexey Fomenko from, prl_from, fromsym, from_p, 156537ed19d5SAlexey Fomenko to, prl_to, tosym, to_p, 156637ed19d5SAlexey Fomenko prl_to, tosym, to_p); 156737ed19d5SAlexey Fomenko free(prl_from); 156837ed19d5SAlexey Fomenko free(prl_to); 1569588ccd73SSam Ravnborg break; 1570588ccd73SSam Ravnborg case EXPORT_TO_INIT_EXIT: 157137ed19d5SAlexey Fomenko prl_to = sec2annotation(tosec); 1572588ccd73SSam Ravnborg fprintf(stderr, 1573588ccd73SSam Ravnborg "The symbol %s is exported and annotated %s\n" 1574588ccd73SSam Ravnborg "Fix this by removing the %sannotation of %s " 1575588ccd73SSam Ravnborg "or drop the export.\n", 157637ed19d5SAlexey Fomenko tosym, prl_to, prl_to, tosym); 157737ed19d5SAlexey Fomenko free(prl_to); 1578588ccd73SSam Ravnborg break; 157952dc0595SQuentin Casasnovas case EXTABLE_TO_NON_TEXT: 158052dc0595SQuentin Casasnovas fatal("There's a special handler for this mismatch type, " 158152dc0595SQuentin Casasnovas "we should never get here."); 158252dc0595SQuentin Casasnovas break; 1583588ccd73SSam Ravnborg } 1584588ccd73SSam Ravnborg fprintf(stderr, "\n"); 158558fb0d4fSSam Ravnborg } 158658fb0d4fSSam Ravnborg 1587644e8f14SQuentin Casasnovas static void default_mismatch_handler(const char *modname, struct elf_info *elf, 1588644e8f14SQuentin Casasnovas const struct sectioncheck* const mismatch, 158958fb0d4fSSam Ravnborg Elf_Rela *r, Elf_Sym *sym, const char *fromsec) 159058fb0d4fSSam Ravnborg { 159158fb0d4fSSam Ravnborg const char *tosec; 1592588ccd73SSam Ravnborg Elf_Sym *to; 1593588ccd73SSam Ravnborg Elf_Sym *from; 159458fb0d4fSSam Ravnborg const char *tosym; 1595588ccd73SSam Ravnborg const char *fromsym; 159658fb0d4fSSam Ravnborg 1597588ccd73SSam Ravnborg from = find_elf_symbol2(elf, r->r_offset, fromsec); 1598588ccd73SSam Ravnborg fromsym = sym_name(elf, from); 159958fb0d4fSSam Ravnborg 1600d62c4765SMasahiro Yamada if (strstarts(fromsym, "reference___initcall")) 160177ab21adSAndi Kleen return; 160277ab21adSAndi Kleen 1603c7a65e06SQuentin Casasnovas tosec = sec_name(elf, get_secindex(elf, sym)); 1604c7a65e06SQuentin Casasnovas to = find_elf_symbol(elf, r->r_addend, sym); 1605c7a65e06SQuentin Casasnovas tosym = sym_name(elf, to); 1606c7a65e06SQuentin Casasnovas 160758fb0d4fSSam Ravnborg /* check whitelist - we may ignore it */ 1608af92a82dSUwe Kleine-König if (secref_whitelist(mismatch, 1609af92a82dSUwe Kleine-König fromsec, fromsym, tosec, tosym)) { 1610588ccd73SSam Ravnborg report_sec_mismatch(modname, mismatch, 1611588ccd73SSam Ravnborg fromsec, r->r_offset, fromsym, 1612588ccd73SSam Ravnborg is_function(from), tosec, tosym, 1613588ccd73SSam Ravnborg is_function(to)); 161458fb0d4fSSam Ravnborg } 1615b39927cfSSam Ravnborg } 1616644e8f14SQuentin Casasnovas 161752dc0595SQuentin Casasnovas static int is_executable_section(struct elf_info* elf, unsigned int section_index) 161852dc0595SQuentin Casasnovas { 161952dc0595SQuentin Casasnovas if (section_index > elf->num_sections) 162052dc0595SQuentin Casasnovas fatal("section_index is outside elf->num_sections!\n"); 162152dc0595SQuentin Casasnovas 162252dc0595SQuentin Casasnovas return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR); 162352dc0595SQuentin Casasnovas } 162452dc0595SQuentin Casasnovas 162552dc0595SQuentin Casasnovas /* 162652dc0595SQuentin Casasnovas * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size() 162752dc0595SQuentin Casasnovas * to know the sizeof(struct exception_table_entry) for the target architecture. 162852dc0595SQuentin Casasnovas */ 162952dc0595SQuentin Casasnovas static unsigned int extable_entry_size = 0; 1630e84048aaSQuentin Casasnovas static void find_extable_entry_size(const char* const sec, const Elf_Rela* r) 163152dc0595SQuentin Casasnovas { 163252dc0595SQuentin Casasnovas /* 163352dc0595SQuentin Casasnovas * If we're currently checking the second relocation within __ex_table, 163452dc0595SQuentin Casasnovas * that relocation offset tells us the offsetof(struct 163552dc0595SQuentin Casasnovas * exception_table_entry, fixup) which is equal to sizeof(struct 163652dc0595SQuentin Casasnovas * exception_table_entry) divided by two. We use that to our advantage 163752dc0595SQuentin Casasnovas * since there's no portable way to get that size as every architecture 163852dc0595SQuentin Casasnovas * seems to go with different sized types. Not pretty but better than 163952dc0595SQuentin Casasnovas * hard-coding the size for every architecture.. 164052dc0595SQuentin Casasnovas */ 1641e84048aaSQuentin Casasnovas if (!extable_entry_size) 164252dc0595SQuentin Casasnovas extable_entry_size = r->r_offset * 2; 164352dc0595SQuentin Casasnovas } 1644e84048aaSQuentin Casasnovas 164552dc0595SQuentin Casasnovas static inline bool is_extable_fault_address(Elf_Rela *r) 164652dc0595SQuentin Casasnovas { 1647d3df4de7SQuentin Casasnovas /* 1648d3df4de7SQuentin Casasnovas * extable_entry_size is only discovered after we've handled the 1649d3df4de7SQuentin Casasnovas * _second_ relocation in __ex_table, so only abort when we're not 1650d3df4de7SQuentin Casasnovas * handling the first reloc and extable_entry_size is zero. 1651d3df4de7SQuentin Casasnovas */ 1652d3df4de7SQuentin Casasnovas if (r->r_offset && extable_entry_size == 0) 165352dc0595SQuentin Casasnovas fatal("extable_entry size hasn't been discovered!\n"); 165452dc0595SQuentin Casasnovas 165552dc0595SQuentin Casasnovas return ((r->r_offset == 0) || 165652dc0595SQuentin Casasnovas (r->r_offset % extable_entry_size == 0)); 165752dc0595SQuentin Casasnovas } 165852dc0595SQuentin Casasnovas 1659e84048aaSQuentin Casasnovas #define is_second_extable_reloc(Start, Cur, Sec) \ 1660e84048aaSQuentin Casasnovas (((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0)) 1661e84048aaSQuentin Casasnovas 166252dc0595SQuentin Casasnovas static void report_extable_warnings(const char* modname, struct elf_info* elf, 166352dc0595SQuentin Casasnovas const struct sectioncheck* const mismatch, 166452dc0595SQuentin Casasnovas Elf_Rela* r, Elf_Sym* sym, 166552dc0595SQuentin Casasnovas const char* fromsec, const char* tosec) 166652dc0595SQuentin Casasnovas { 166752dc0595SQuentin Casasnovas Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec); 166852dc0595SQuentin Casasnovas const char* fromsym_name = sym_name(elf, fromsym); 166952dc0595SQuentin Casasnovas Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym); 167052dc0595SQuentin Casasnovas const char* tosym_name = sym_name(elf, tosym); 167152dc0595SQuentin Casasnovas const char* from_pretty_name; 167252dc0595SQuentin Casasnovas const char* from_pretty_name_p; 167352dc0595SQuentin Casasnovas const char* to_pretty_name; 167452dc0595SQuentin Casasnovas const char* to_pretty_name_p; 167552dc0595SQuentin Casasnovas 167652dc0595SQuentin Casasnovas get_pretty_name(is_function(fromsym), 167752dc0595SQuentin Casasnovas &from_pretty_name, &from_pretty_name_p); 167852dc0595SQuentin Casasnovas get_pretty_name(is_function(tosym), 167952dc0595SQuentin Casasnovas &to_pretty_name, &to_pretty_name_p); 168052dc0595SQuentin Casasnovas 168152dc0595SQuentin Casasnovas warn("%s(%s+0x%lx): Section mismatch in reference" 168252dc0595SQuentin Casasnovas " from the %s %s%s to the %s %s:%s%s\n", 168352dc0595SQuentin Casasnovas modname, fromsec, (long)r->r_offset, from_pretty_name, 168452dc0595SQuentin Casasnovas fromsym_name, from_pretty_name_p, 168552dc0595SQuentin Casasnovas to_pretty_name, tosec, tosym_name, to_pretty_name_p); 168652dc0595SQuentin Casasnovas 168752dc0595SQuentin Casasnovas if (!match(tosec, mismatch->bad_tosec) && 168852dc0595SQuentin Casasnovas is_executable_section(elf, get_secindex(elf, sym))) 168952dc0595SQuentin Casasnovas fprintf(stderr, 169052dc0595SQuentin Casasnovas "The relocation at %s+0x%lx references\n" 169152dc0595SQuentin Casasnovas "section \"%s\" which is not in the list of\n" 169252dc0595SQuentin Casasnovas "authorized sections. If you're adding a new section\n" 169352dc0595SQuentin Casasnovas "and/or if this reference is valid, add \"%s\" to the\n" 169452dc0595SQuentin Casasnovas "list of authorized sections to jump to on fault.\n" 169552dc0595SQuentin Casasnovas "This can be achieved by adding \"%s\" to \n" 169652dc0595SQuentin Casasnovas "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n", 169752dc0595SQuentin Casasnovas fromsec, (long)r->r_offset, tosec, tosec, tosec); 169852dc0595SQuentin Casasnovas } 169952dc0595SQuentin Casasnovas 170052dc0595SQuentin Casasnovas static void extable_mismatch_handler(const char* modname, struct elf_info *elf, 170152dc0595SQuentin Casasnovas const struct sectioncheck* const mismatch, 170252dc0595SQuentin Casasnovas Elf_Rela* r, Elf_Sym* sym, 170352dc0595SQuentin Casasnovas const char *fromsec) 170452dc0595SQuentin Casasnovas { 170552dc0595SQuentin Casasnovas const char* tosec = sec_name(elf, get_secindex(elf, sym)); 170652dc0595SQuentin Casasnovas 170752dc0595SQuentin Casasnovas sec_mismatch_count++; 170852dc0595SQuentin Casasnovas 170946c7dd56SMasahiro Yamada report_extable_warnings(modname, elf, mismatch, r, sym, fromsec, tosec); 171052dc0595SQuentin Casasnovas 171152dc0595SQuentin Casasnovas if (match(tosec, mismatch->bad_tosec)) 171252dc0595SQuentin Casasnovas fatal("The relocation at %s+0x%lx references\n" 171352dc0595SQuentin Casasnovas "section \"%s\" which is black-listed.\n" 171452dc0595SQuentin Casasnovas "Something is seriously wrong and should be fixed.\n" 171552dc0595SQuentin Casasnovas "You might get more information about where this is\n" 171652dc0595SQuentin Casasnovas "coming from by using scripts/check_extable.sh %s\n", 171752dc0595SQuentin Casasnovas fromsec, (long)r->r_offset, tosec, modname); 171852dc0595SQuentin Casasnovas else if (!is_executable_section(elf, get_secindex(elf, sym))) { 171952dc0595SQuentin Casasnovas if (is_extable_fault_address(r)) 172052dc0595SQuentin Casasnovas fatal("The relocation at %s+0x%lx references\n" 172152dc0595SQuentin Casasnovas "section \"%s\" which is not executable, IOW\n" 172252dc0595SQuentin Casasnovas "it is not possible for the kernel to fault\n" 172352dc0595SQuentin Casasnovas "at that address. Something is seriously wrong\n" 172452dc0595SQuentin Casasnovas "and should be fixed.\n", 172552dc0595SQuentin Casasnovas fromsec, (long)r->r_offset, tosec); 172652dc0595SQuentin Casasnovas else 172752dc0595SQuentin Casasnovas fatal("The relocation at %s+0x%lx references\n" 172852dc0595SQuentin Casasnovas "section \"%s\" which is not executable, IOW\n" 172952dc0595SQuentin Casasnovas "the kernel will fault if it ever tries to\n" 173052dc0595SQuentin Casasnovas "jump to it. Something is seriously wrong\n" 173152dc0595SQuentin Casasnovas "and should be fixed.\n", 173252dc0595SQuentin Casasnovas fromsec, (long)r->r_offset, tosec); 173352dc0595SQuentin Casasnovas } 173452dc0595SQuentin Casasnovas } 173552dc0595SQuentin Casasnovas 1736644e8f14SQuentin Casasnovas static void check_section_mismatch(const char *modname, struct elf_info *elf, 1737644e8f14SQuentin Casasnovas Elf_Rela *r, Elf_Sym *sym, const char *fromsec) 1738644e8f14SQuentin Casasnovas { 17390cad61d7SLuis de Bethencourt const char *tosec = sec_name(elf, get_secindex(elf, sym)); 1740644e8f14SQuentin Casasnovas const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec); 1741644e8f14SQuentin Casasnovas 1742644e8f14SQuentin Casasnovas if (mismatch) { 1743644e8f14SQuentin Casasnovas if (mismatch->handler) 1744644e8f14SQuentin Casasnovas mismatch->handler(modname, elf, mismatch, 1745644e8f14SQuentin Casasnovas r, sym, fromsec); 1746644e8f14SQuentin Casasnovas else 1747644e8f14SQuentin Casasnovas default_mismatch_handler(modname, elf, mismatch, 1748644e8f14SQuentin Casasnovas r, sym, fromsec); 1749644e8f14SQuentin Casasnovas } 1750b39927cfSSam Ravnborg } 1751b39927cfSSam Ravnborg 1752ae4ac123SAtsushi Nemoto static unsigned int *reloc_location(struct elf_info *elf, 17535b24c071SSam Ravnborg Elf_Shdr *sechdr, Elf_Rela *r) 1754ae4ac123SAtsushi Nemoto { 1755ae4ac123SAtsushi Nemoto Elf_Shdr *sechdrs = elf->sechdrs; 17566845756bSAnders Kaseorg int section = sechdr->sh_info; 1757ae4ac123SAtsushi Nemoto 1758ae4ac123SAtsushi Nemoto return (void *)elf->hdr + sechdrs[section].sh_offset + 1759731ece41SOlof Johansson r->r_offset; 1760ae4ac123SAtsushi Nemoto } 1761ae4ac123SAtsushi Nemoto 17625b24c071SSam Ravnborg static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 1763ae4ac123SAtsushi Nemoto { 1764ae4ac123SAtsushi Nemoto unsigned int r_typ = ELF_R_TYPE(r->r_info); 17655b24c071SSam Ravnborg unsigned int *location = reloc_location(elf, sechdr, r); 1766ae4ac123SAtsushi Nemoto 1767ae4ac123SAtsushi Nemoto switch (r_typ) { 1768ae4ac123SAtsushi Nemoto case R_386_32: 1769ae4ac123SAtsushi Nemoto r->r_addend = TO_NATIVE(*location); 1770ae4ac123SAtsushi Nemoto break; 1771ae4ac123SAtsushi Nemoto case R_386_PC32: 1772ae4ac123SAtsushi Nemoto r->r_addend = TO_NATIVE(*location) + 4; 1773ae4ac123SAtsushi Nemoto /* For CONFIG_RELOCATABLE=y */ 1774ae4ac123SAtsushi Nemoto if (elf->hdr->e_type == ET_EXEC) 1775ae4ac123SAtsushi Nemoto r->r_addend += r->r_offset; 1776ae4ac123SAtsushi Nemoto break; 1777ae4ac123SAtsushi Nemoto } 1778ae4ac123SAtsushi Nemoto return 0; 1779ae4ac123SAtsushi Nemoto } 1780ae4ac123SAtsushi Nemoto 17816e2e340bSTony Lindgren #ifndef R_ARM_CALL 17826e2e340bSTony Lindgren #define R_ARM_CALL 28 17836e2e340bSTony Lindgren #endif 17846e2e340bSTony Lindgren #ifndef R_ARM_JUMP24 17856e2e340bSTony Lindgren #define R_ARM_JUMP24 29 17866e2e340bSTony Lindgren #endif 17876e2e340bSTony Lindgren 1788c9698e5cSDavid A. Long #ifndef R_ARM_THM_CALL 1789c9698e5cSDavid A. Long #define R_ARM_THM_CALL 10 1790c9698e5cSDavid A. Long #endif 1791c9698e5cSDavid A. Long #ifndef R_ARM_THM_JUMP24 1792c9698e5cSDavid A. Long #define R_ARM_THM_JUMP24 30 1793c9698e5cSDavid A. Long #endif 1794c9698e5cSDavid A. Long #ifndef R_ARM_THM_JUMP19 1795c9698e5cSDavid A. Long #define R_ARM_THM_JUMP19 51 1796c9698e5cSDavid A. Long #endif 1797c9698e5cSDavid A. Long 17985b24c071SSam Ravnborg static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 179956a974faSSam Ravnborg { 180056a974faSSam Ravnborg unsigned int r_typ = ELF_R_TYPE(r->r_info); 180156a974faSSam Ravnborg 180256a974faSSam Ravnborg switch (r_typ) { 180356a974faSSam Ravnborg case R_ARM_ABS32: 180456a974faSSam Ravnborg /* From ARM ABI: (S + A) | T */ 1805df578e7dSSam Ravnborg r->r_addend = (int)(long) 1806df578e7dSSam Ravnborg (elf->symtab_start + ELF_R_SYM(r->r_info)); 180756a974faSSam Ravnborg break; 180856a974faSSam Ravnborg case R_ARM_PC24: 18096e2e340bSTony Lindgren case R_ARM_CALL: 18106e2e340bSTony Lindgren case R_ARM_JUMP24: 1811c9698e5cSDavid A. Long case R_ARM_THM_CALL: 1812c9698e5cSDavid A. Long case R_ARM_THM_JUMP24: 1813c9698e5cSDavid A. Long case R_ARM_THM_JUMP19: 181456a974faSSam Ravnborg /* From ARM ABI: ((S + A) | T) - P */ 1815df578e7dSSam Ravnborg r->r_addend = (int)(long)(elf->hdr + 18165b24c071SSam Ravnborg sechdr->sh_offset + 18175b24c071SSam Ravnborg (r->r_offset - sechdr->sh_addr)); 181856a974faSSam Ravnborg break; 181956a974faSSam Ravnborg default: 182056a974faSSam Ravnborg return 1; 182156a974faSSam Ravnborg } 182256a974faSSam Ravnborg return 0; 182356a974faSSam Ravnborg } 182456a974faSSam Ravnborg 18255b24c071SSam Ravnborg static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) 1826ae4ac123SAtsushi Nemoto { 1827ae4ac123SAtsushi Nemoto unsigned int r_typ = ELF_R_TYPE(r->r_info); 18285b24c071SSam Ravnborg unsigned int *location = reloc_location(elf, sechdr, r); 1829ae4ac123SAtsushi Nemoto unsigned int inst; 1830ae4ac123SAtsushi Nemoto 1831ae4ac123SAtsushi Nemoto if (r_typ == R_MIPS_HI16) 1832ae4ac123SAtsushi Nemoto return 1; /* skip this */ 1833ae4ac123SAtsushi Nemoto inst = TO_NATIVE(*location); 1834ae4ac123SAtsushi Nemoto switch (r_typ) { 1835ae4ac123SAtsushi Nemoto case R_MIPS_LO16: 1836ae4ac123SAtsushi Nemoto r->r_addend = inst & 0xffff; 1837ae4ac123SAtsushi Nemoto break; 1838ae4ac123SAtsushi Nemoto case R_MIPS_26: 1839ae4ac123SAtsushi Nemoto r->r_addend = (inst & 0x03ffffff) << 2; 1840ae4ac123SAtsushi Nemoto break; 1841ae4ac123SAtsushi Nemoto case R_MIPS_32: 1842ae4ac123SAtsushi Nemoto r->r_addend = inst; 1843ae4ac123SAtsushi Nemoto break; 1844ae4ac123SAtsushi Nemoto } 1845ae4ac123SAtsushi Nemoto return 0; 1846ae4ac123SAtsushi Nemoto } 1847ae4ac123SAtsushi Nemoto 18485b24c071SSam Ravnborg static void section_rela(const char *modname, struct elf_info *elf, 184910668220SSam Ravnborg Elf_Shdr *sechdr) 1850b39927cfSSam Ravnborg { 1851b39927cfSSam Ravnborg Elf_Sym *sym; 18525b24c071SSam Ravnborg Elf_Rela *rela; 18532c1a51f3SAtsushi Nemoto Elf_Rela r; 1854eae07ac6SAtsushi Nemoto unsigned int r_sym; 18555b24c071SSam Ravnborg const char *fromsec; 18565b24c071SSam Ravnborg 1857ff13f926SSam Ravnborg Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; 18585b24c071SSam Ravnborg Elf_Rela *stop = (void *)start + sechdr->sh_size; 18595b24c071SSam Ravnborg 1860ff13f926SSam Ravnborg fromsec = sech_name(elf, sechdr); 18615b24c071SSam Ravnborg fromsec += strlen(".rela"); 18625b24c071SSam Ravnborg /* if from section (name) is know good then skip it */ 1863b614a697SAnders Kaseorg if (match(fromsec, section_white_list)) 18645b24c071SSam Ravnborg return; 1865e241a630SSam Ravnborg 1866b39927cfSSam Ravnborg for (rela = start; rela < stop; rela++) { 1867b39927cfSSam Ravnborg r.r_offset = TO_NATIVE(rela->r_offset); 1868eae07ac6SAtsushi Nemoto #if KERNEL_ELFCLASS == ELFCLASS64 1869ff13f926SSam Ravnborg if (elf->hdr->e_machine == EM_MIPS) { 1870ae4ac123SAtsushi Nemoto unsigned int r_typ; 1871eae07ac6SAtsushi Nemoto r_sym = ELF64_MIPS_R_SYM(rela->r_info); 1872eae07ac6SAtsushi Nemoto r_sym = TO_NATIVE(r_sym); 1873ae4ac123SAtsushi Nemoto r_typ = ELF64_MIPS_R_TYPE(rela->r_info); 1874ae4ac123SAtsushi Nemoto r.r_info = ELF64_R_INFO(r_sym, r_typ); 1875eae07ac6SAtsushi Nemoto } else { 1876601e7f02SLinus Torvalds r.r_info = TO_NATIVE(rela->r_info); 1877eae07ac6SAtsushi Nemoto r_sym = ELF_R_SYM(r.r_info); 1878eae07ac6SAtsushi Nemoto } 1879eae07ac6SAtsushi Nemoto #else 1880eae07ac6SAtsushi Nemoto r.r_info = TO_NATIVE(rela->r_info); 1881eae07ac6SAtsushi Nemoto r_sym = ELF_R_SYM(r.r_info); 1882eae07ac6SAtsushi Nemoto #endif 188393684d3bSSam Ravnborg r.r_addend = TO_NATIVE(rela->r_addend); 1884eae07ac6SAtsushi Nemoto sym = elf->symtab_start + r_sym; 1885b39927cfSSam Ravnborg /* Skip special sections */ 18861ce53adfSDenys Vlasenko if (is_shndx_special(sym->st_shndx)) 1887b39927cfSSam Ravnborg continue; 1888e84048aaSQuentin Casasnovas if (is_second_extable_reloc(start, rela, fromsec)) 1889e84048aaSQuentin Casasnovas find_extable_entry_size(fromsec, &r); 189058fb0d4fSSam Ravnborg check_section_mismatch(modname, elf, &r, sym, fromsec); 18912c1a51f3SAtsushi Nemoto } 18925b24c071SSam Ravnborg } 18935b24c071SSam Ravnborg 18945b24c071SSam Ravnborg static void section_rel(const char *modname, struct elf_info *elf, 189510668220SSam Ravnborg Elf_Shdr *sechdr) 18965b24c071SSam Ravnborg { 18975b24c071SSam Ravnborg Elf_Sym *sym; 18982c1a51f3SAtsushi Nemoto Elf_Rel *rel; 18995b24c071SSam Ravnborg Elf_Rela r; 19005b24c071SSam Ravnborg unsigned int r_sym; 19015b24c071SSam Ravnborg const char *fromsec; 19025b24c071SSam Ravnborg 1903ff13f926SSam Ravnborg Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; 19045b24c071SSam Ravnborg Elf_Rel *stop = (void *)start + sechdr->sh_size; 19055b24c071SSam Ravnborg 1906ff13f926SSam Ravnborg fromsec = sech_name(elf, sechdr); 19075b24c071SSam Ravnborg fromsec += strlen(".rel"); 19085b24c071SSam Ravnborg /* if from section (name) is know good then skip it */ 1909b614a697SAnders Kaseorg if (match(fromsec, section_white_list)) 19105b24c071SSam Ravnborg return; 19112c1a51f3SAtsushi Nemoto 19122c1a51f3SAtsushi Nemoto for (rel = start; rel < stop; rel++) { 19132c1a51f3SAtsushi Nemoto r.r_offset = TO_NATIVE(rel->r_offset); 1914eae07ac6SAtsushi Nemoto #if KERNEL_ELFCLASS == ELFCLASS64 1915ff13f926SSam Ravnborg if (elf->hdr->e_machine == EM_MIPS) { 1916ae4ac123SAtsushi Nemoto unsigned int r_typ; 1917eae07ac6SAtsushi Nemoto r_sym = ELF64_MIPS_R_SYM(rel->r_info); 1918eae07ac6SAtsushi Nemoto r_sym = TO_NATIVE(r_sym); 1919ae4ac123SAtsushi Nemoto r_typ = ELF64_MIPS_R_TYPE(rel->r_info); 1920ae4ac123SAtsushi Nemoto r.r_info = ELF64_R_INFO(r_sym, r_typ); 1921eae07ac6SAtsushi Nemoto } else { 19222c1a51f3SAtsushi Nemoto r.r_info = TO_NATIVE(rel->r_info); 1923eae07ac6SAtsushi Nemoto r_sym = ELF_R_SYM(r.r_info); 1924eae07ac6SAtsushi Nemoto } 1925eae07ac6SAtsushi Nemoto #else 1926eae07ac6SAtsushi Nemoto r.r_info = TO_NATIVE(rel->r_info); 1927eae07ac6SAtsushi Nemoto r_sym = ELF_R_SYM(r.r_info); 1928eae07ac6SAtsushi Nemoto #endif 19292c1a51f3SAtsushi Nemoto r.r_addend = 0; 1930ff13f926SSam Ravnborg switch (elf->hdr->e_machine) { 1931ae4ac123SAtsushi Nemoto case EM_386: 19325b24c071SSam Ravnborg if (addend_386_rel(elf, sechdr, &r)) 1933ae4ac123SAtsushi Nemoto continue; 1934ae4ac123SAtsushi Nemoto break; 193556a974faSSam Ravnborg case EM_ARM: 19365b24c071SSam Ravnborg if (addend_arm_rel(elf, sechdr, &r)) 193756a974faSSam Ravnborg continue; 193856a974faSSam Ravnborg break; 1939ae4ac123SAtsushi Nemoto case EM_MIPS: 19405b24c071SSam Ravnborg if (addend_mips_rel(elf, sechdr, &r)) 1941ae4ac123SAtsushi Nemoto continue; 1942ae4ac123SAtsushi Nemoto break; 1943ae4ac123SAtsushi Nemoto } 1944eae07ac6SAtsushi Nemoto sym = elf->symtab_start + r_sym; 19452c1a51f3SAtsushi Nemoto /* Skip special sections */ 19461ce53adfSDenys Vlasenko if (is_shndx_special(sym->st_shndx)) 19472c1a51f3SAtsushi Nemoto continue; 1948e84048aaSQuentin Casasnovas if (is_second_extable_reloc(start, rel, fromsec)) 1949e84048aaSQuentin Casasnovas find_extable_entry_size(fromsec, &r); 195058fb0d4fSSam Ravnborg check_section_mismatch(modname, elf, &r, sym, fromsec); 19512c1a51f3SAtsushi Nemoto } 1952b39927cfSSam Ravnborg } 19535b24c071SSam Ravnborg 19545b24c071SSam Ravnborg /** 19555b24c071SSam Ravnborg * A module includes a number of sections that are discarded 19565b24c071SSam Ravnborg * either when loaded or when used as built-in. 19575b24c071SSam Ravnborg * For loaded modules all functions marked __init and all data 1958b595076aSUwe Kleine-König * marked __initdata will be discarded when the module has been initialized. 19595b24c071SSam Ravnborg * Likewise for modules used built-in the sections marked __exit 19605b24c071SSam Ravnborg * are discarded because __exit marked function are supposed to be called 196132be1d22SBen Dooks * only when a module is unloaded which never happens for built-in modules. 19625b24c071SSam Ravnborg * The check_sec_ref() function traverses all relocation records 19635b24c071SSam Ravnborg * to find all references to a section that reference a section that will 19645b24c071SSam Ravnborg * be discarded and warns about it. 19655b24c071SSam Ravnborg **/ 19665b24c071SSam Ravnborg static void check_sec_ref(struct module *mod, const char *modname, 196710668220SSam Ravnborg struct elf_info *elf) 19685b24c071SSam Ravnborg { 19695b24c071SSam Ravnborg int i; 19705b24c071SSam Ravnborg Elf_Shdr *sechdrs = elf->sechdrs; 19715b24c071SSam Ravnborg 19725b24c071SSam Ravnborg /* Walk through all sections */ 19731ce53adfSDenys Vlasenko for (i = 0; i < elf->num_sections; i++) { 1974b614a697SAnders Kaseorg check_section(modname, elf, &elf->sechdrs[i]); 19755b24c071SSam Ravnborg /* We want to process only relocation sections and not .init */ 19765b24c071SSam Ravnborg if (sechdrs[i].sh_type == SHT_RELA) 197710668220SSam Ravnborg section_rela(modname, elf, &elf->sechdrs[i]); 19785b24c071SSam Ravnborg else if (sechdrs[i].sh_type == SHT_REL) 197910668220SSam Ravnborg section_rel(modname, elf, &elf->sechdrs[i]); 1980b39927cfSSam Ravnborg } 1981b39927cfSSam Ravnborg } 1982b39927cfSSam Ravnborg 19837d02b490SAndi Kleen static char *remove_dot(char *s) 19847d02b490SAndi Kleen { 1985fcd38ed0SMichal Nazarewicz size_t n = strcspn(s, "."); 19867d02b490SAndi Kleen 1987fcd38ed0SMichal Nazarewicz if (n && s[n]) { 1988fcd38ed0SMichal Nazarewicz size_t m = strspn(s + n + 1, "0123456789"); 1989fcd38ed0SMichal Nazarewicz if (m && (s[n + m] == '.' || s[n + m] == 0)) 19907d02b490SAndi Kleen s[n] = 0; 19917d02b490SAndi Kleen } 19927d02b490SAndi Kleen return s; 19937d02b490SAndi Kleen } 19947d02b490SAndi Kleen 19958b185743SMasahiro Yamada static void read_symbols(const char *modname) 19961da177e4SLinus Torvalds { 19971da177e4SLinus Torvalds const char *symname; 19981da177e4SLinus Torvalds char *version; 1999b817f6feSSam Ravnborg char *license; 2000cb9b55d2SMatthias Maennich char *namespace; 20011da177e4SLinus Torvalds struct module *mod; 20021da177e4SLinus Torvalds struct elf_info info = { }; 20031da177e4SLinus Torvalds Elf_Sym *sym; 20041da177e4SLinus Torvalds 200585bd2fddSSam Ravnborg if (!parse_elf(&info, modname)) 200685bd2fddSSam Ravnborg return; 20071da177e4SLinus Torvalds 20081da177e4SLinus Torvalds mod = new_module(modname); 20091da177e4SLinus Torvalds 20101da177e4SLinus Torvalds /* When there's no vmlinux, don't print warnings about 20111da177e4SLinus Torvalds * unresolved symbols (since there'll be too many ;) */ 20121da177e4SLinus Torvalds if (is_vmlinux(modname)) { 20131da177e4SLinus Torvalds have_vmlinux = 1; 20141da177e4SLinus Torvalds mod->skip = 1; 20151da177e4SLinus Torvalds } 20161da177e4SLinus Torvalds 2017bca2cceeSMasahiro Yamada license = get_modinfo(&info, "license"); 2018ba1029c9SRandy Dunlap if (!license && !is_vmlinux(modname)) 20192fa36568SSam Ravnborg warn("modpost: missing MODULE_LICENSE() in %s\n" 2020eed7d279SSam Ravnborg "see include/linux/module.h for " 2021eed7d279SSam Ravnborg "more information\n", modname); 2022b817f6feSSam Ravnborg while (license) { 2023b817f6feSSam Ravnborg if (license_is_gpl_compatible(license)) 2024b817f6feSSam Ravnborg mod->gpl_compatible = 1; 2025b817f6feSSam Ravnborg else { 2026b817f6feSSam Ravnborg mod->gpl_compatible = 0; 2027b817f6feSSam Ravnborg break; 2028b817f6feSSam Ravnborg } 2029bca2cceeSMasahiro Yamada license = get_next_modinfo(&info, "license", license); 2030b817f6feSSam Ravnborg } 2031b817f6feSSam Ravnborg 2032cb9b55d2SMatthias Maennich namespace = get_modinfo(&info, "import_ns"); 2033cb9b55d2SMatthias Maennich while (namespace) { 2034cb9b55d2SMatthias Maennich add_namespace(&mod->imported_namespaces, namespace); 2035cb9b55d2SMatthias Maennich namespace = get_next_modinfo(&info, "import_ns", namespace); 2036cb9b55d2SMatthias Maennich } 2037cb9b55d2SMatthias Maennich 20381da177e4SLinus Torvalds for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { 20397d02b490SAndi Kleen symname = remove_dot(info.strtab + sym->st_name); 20401da177e4SLinus Torvalds 20411da177e4SLinus Torvalds handle_modversions(mod, &info, sym, symname); 20421da177e4SLinus Torvalds handle_moddevtable(mod, &info, sym, symname); 20431da177e4SLinus Torvalds } 204415bfc234SDenis Efremov 204515bfc234SDenis Efremov // check for static EXPORT_SYMBOL_* functions && global vars 204615bfc234SDenis Efremov for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { 204715bfc234SDenis Efremov unsigned char bind = ELF_ST_BIND(sym->st_info); 204815bfc234SDenis Efremov 204915bfc234SDenis Efremov if (bind == STB_GLOBAL || bind == STB_WEAK) { 205015bfc234SDenis Efremov struct symbol *s = 205115bfc234SDenis Efremov find_symbol(remove_dot(info.strtab + 205215bfc234SDenis Efremov sym->st_name)); 205315bfc234SDenis Efremov 205415bfc234SDenis Efremov if (s) 205515bfc234SDenis Efremov s->is_static = 0; 205615bfc234SDenis Efremov } 205715bfc234SDenis Efremov } 205815bfc234SDenis Efremov 2059074a04f5SMasahiro Yamada if (!is_vmlinux(modname) || vmlinux_section_warnings) 206010668220SSam Ravnborg check_sec_ref(mod, modname, &info); 20611da177e4SLinus Torvalds 2062bca2cceeSMasahiro Yamada version = get_modinfo(&info, "version"); 20631da177e4SLinus Torvalds if (version) 20641da177e4SLinus Torvalds maybe_frob_rcs_version(modname, version, info.modinfo, 20651da177e4SLinus Torvalds version - (char *)info.hdr); 20661da177e4SLinus Torvalds if (version || (all_versions && !is_vmlinux(modname))) 20671da177e4SLinus Torvalds get_src_version(modname, mod->srcversion, 20681da177e4SLinus Torvalds sizeof(mod->srcversion)-1); 20691da177e4SLinus Torvalds 20701da177e4SLinus Torvalds parse_elf_finish(&info); 20711da177e4SLinus Torvalds 20728c8ef42aSRusty Russell /* Our trick to get versioning for module struct etc. - it's 20731da177e4SLinus Torvalds * never passed as an argument to an exported function, so 20741da177e4SLinus Torvalds * the automatic versioning doesn't pick it up, but it's really 20751da177e4SLinus Torvalds * important anyhow */ 20761da177e4SLinus Torvalds if (modversions) 20778c8ef42aSRusty Russell mod->unres = alloc_symbol("module_layout", 0, mod->unres); 20781da177e4SLinus Torvalds } 20791da177e4SLinus Torvalds 2080712f9b46SRusty Russell static void read_symbols_from_files(const char *filename) 2081712f9b46SRusty Russell { 2082712f9b46SRusty Russell FILE *in = stdin; 2083712f9b46SRusty Russell char fname[PATH_MAX]; 2084712f9b46SRusty Russell 2085712f9b46SRusty Russell if (strcmp(filename, "-") != 0) { 2086712f9b46SRusty Russell in = fopen(filename, "r"); 2087712f9b46SRusty Russell if (!in) 2088712f9b46SRusty Russell fatal("Can't open filenames file %s: %m", filename); 2089712f9b46SRusty Russell } 2090712f9b46SRusty Russell 2091712f9b46SRusty Russell while (fgets(fname, PATH_MAX, in) != NULL) { 2092712f9b46SRusty Russell if (strends(fname, "\n")) 2093712f9b46SRusty Russell fname[strlen(fname)-1] = '\0'; 2094712f9b46SRusty Russell read_symbols(fname); 2095712f9b46SRusty Russell } 2096712f9b46SRusty Russell 2097712f9b46SRusty Russell if (in != stdin) 2098712f9b46SRusty Russell fclose(in); 2099712f9b46SRusty Russell } 2100712f9b46SRusty Russell 21011da177e4SLinus Torvalds #define SZ 500 21021da177e4SLinus Torvalds 21031da177e4SLinus Torvalds /* We first write the generated file into memory using the 21041da177e4SLinus Torvalds * following helper, then compare to the file on disk and 21051da177e4SLinus Torvalds * only update the later if anything changed */ 21061da177e4SLinus Torvalds 21075c3ead8cSSam Ravnborg void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf, 21085c3ead8cSSam Ravnborg const char *fmt, ...) 21091da177e4SLinus Torvalds { 21101da177e4SLinus Torvalds char tmp[SZ]; 21111da177e4SLinus Torvalds int len; 21121da177e4SLinus Torvalds va_list ap; 21131da177e4SLinus Torvalds 21141da177e4SLinus Torvalds va_start(ap, fmt); 21151da177e4SLinus Torvalds len = vsnprintf(tmp, SZ, fmt, ap); 21167670f023SSam Ravnborg buf_write(buf, tmp, len); 21171da177e4SLinus Torvalds va_end(ap); 21181da177e4SLinus Torvalds } 21191da177e4SLinus Torvalds 21205c3ead8cSSam Ravnborg void buf_write(struct buffer *buf, const char *s, int len) 21211da177e4SLinus Torvalds { 21221da177e4SLinus Torvalds if (buf->size - buf->pos < len) { 21237670f023SSam Ravnborg buf->size += len + SZ; 21241f3aa900SRandy Dunlap buf->p = NOFAIL(realloc(buf->p, buf->size)); 21251da177e4SLinus Torvalds } 21261da177e4SLinus Torvalds strncpy(buf->p + buf->pos, s, len); 21271da177e4SLinus Torvalds buf->pos += len; 21281da177e4SLinus Torvalds } 21291da177e4SLinus Torvalds 2130c96fca21SSam Ravnborg static void check_for_gpl_usage(enum export exp, const char *m, const char *s) 2131c96fca21SSam Ravnborg { 2132c96fca21SSam Ravnborg const char *e = is_vmlinux(m) ?"":".ko"; 2133c96fca21SSam Ravnborg 2134c96fca21SSam Ravnborg switch (exp) { 2135c96fca21SSam Ravnborg case export_gpl: 2136c96fca21SSam Ravnborg fatal("modpost: GPL-incompatible module %s%s " 2137c96fca21SSam Ravnborg "uses GPL-only symbol '%s'\n", m, e, s); 2138c96fca21SSam Ravnborg break; 2139c96fca21SSam Ravnborg case export_unused_gpl: 2140c96fca21SSam Ravnborg fatal("modpost: GPL-incompatible module %s%s " 2141c96fca21SSam Ravnborg "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); 2142c96fca21SSam Ravnborg break; 2143c96fca21SSam Ravnborg case export_gpl_future: 2144c96fca21SSam Ravnborg warn("modpost: GPL-incompatible module %s%s " 2145c96fca21SSam Ravnborg "uses future GPL-only symbol '%s'\n", m, e, s); 2146c96fca21SSam Ravnborg break; 2147c96fca21SSam Ravnborg case export_plain: 2148c96fca21SSam Ravnborg case export_unused: 2149c96fca21SSam Ravnborg case export_unknown: 2150c96fca21SSam Ravnborg /* ignore */ 2151c96fca21SSam Ravnborg break; 2152c96fca21SSam Ravnborg } 2153c96fca21SSam Ravnborg } 2154c96fca21SSam Ravnborg 2155c96fca21SSam Ravnborg static void check_for_unused(enum export exp, const char *m, const char *s) 2156c96fca21SSam Ravnborg { 2157c96fca21SSam Ravnborg const char *e = is_vmlinux(m) ?"":".ko"; 2158c96fca21SSam Ravnborg 2159c96fca21SSam Ravnborg switch (exp) { 2160c96fca21SSam Ravnborg case export_unused: 2161c96fca21SSam Ravnborg case export_unused_gpl: 2162c96fca21SSam Ravnborg warn("modpost: module %s%s " 2163c96fca21SSam Ravnborg "uses symbol '%s' marked UNUSED\n", m, e, s); 2164c96fca21SSam Ravnborg break; 2165c96fca21SSam Ravnborg default: 2166c96fca21SSam Ravnborg /* ignore */ 2167c96fca21SSam Ravnborg break; 2168c96fca21SSam Ravnborg } 2169c96fca21SSam Ravnborg } 2170c96fca21SSam Ravnborg 21713b415288SMasahiro Yamada static int check_exports(struct module *mod) 2172b817f6feSSam Ravnborg { 2173b817f6feSSam Ravnborg struct symbol *s, *exp; 21743b415288SMasahiro Yamada int err = 0; 2175b817f6feSSam Ravnborg 2176b817f6feSSam Ravnborg for (s = mod->unres; s; s = s->next) { 21776449bd62SAndrew Morton const char *basename; 2178b817f6feSSam Ravnborg exp = find_symbol(s->name); 21793b415288SMasahiro Yamada if (!exp || exp->module == mod) { 21803b415288SMasahiro Yamada if (have_vmlinux && !s->weak) { 21813b415288SMasahiro Yamada if (warn_unresolved) { 21823b415288SMasahiro Yamada warn("\"%s\" [%s.ko] undefined!\n", 21833b415288SMasahiro Yamada s->name, mod->name); 21843b415288SMasahiro Yamada } else { 21853b415288SMasahiro Yamada merror("\"%s\" [%s.ko] undefined!\n", 21863b415288SMasahiro Yamada s->name, mod->name); 21873b415288SMasahiro Yamada err = 1; 21883b415288SMasahiro Yamada } 21893b415288SMasahiro Yamada } 2190b817f6feSSam Ravnborg continue; 21913b415288SMasahiro Yamada } 21926449bd62SAndrew Morton basename = strrchr(mod->name, '/'); 2193b817f6feSSam Ravnborg if (basename) 2194b817f6feSSam Ravnborg basename++; 2195c96fca21SSam Ravnborg else 2196c96fca21SSam Ravnborg basename = mod->name; 2197cb9b55d2SMatthias Maennich 21981d082773SMatthias Maennich if (exp->namespace) { 21991d082773SMatthias Maennich add_namespace(&mod->required_namespaces, 22001d082773SMatthias Maennich exp->namespace); 22011d082773SMatthias Maennich 22021d082773SMatthias Maennich if (!write_namespace_deps && 2203cb9b55d2SMatthias Maennich !module_imports_namespace(mod, exp->namespace)) { 2204cb9b55d2SMatthias Maennich warn("module %s uses symbol %s from namespace %s, but does not import it.\n", 2205cb9b55d2SMatthias Maennich basename, exp->name, exp->namespace); 2206cb9b55d2SMatthias Maennich } 22071d082773SMatthias Maennich } 2208cb9b55d2SMatthias Maennich 2209c96fca21SSam Ravnborg if (!mod->gpl_compatible) 2210c96fca21SSam Ravnborg check_for_gpl_usage(exp->export, basename, exp->name); 2211c96fca21SSam Ravnborg check_for_unused(exp->export, basename, exp->name); 2212b817f6feSSam Ravnborg } 22133b415288SMasahiro Yamada 22143b415288SMasahiro Yamada return err; 2215b817f6feSSam Ravnborg } 2216b817f6feSSam Ravnborg 22174fd3e4efSWanlong Gao static int check_modname_len(struct module *mod) 22184fd3e4efSWanlong Gao { 22194fd3e4efSWanlong Gao const char *mod_name; 22204fd3e4efSWanlong Gao 22214fd3e4efSWanlong Gao mod_name = strrchr(mod->name, '/'); 22224fd3e4efSWanlong Gao if (mod_name == NULL) 22234fd3e4efSWanlong Gao mod_name = mod->name; 22244fd3e4efSWanlong Gao else 22254fd3e4efSWanlong Gao mod_name++; 22264fd3e4efSWanlong Gao if (strlen(mod_name) >= MODULE_NAME_LEN) { 22274fd3e4efSWanlong Gao merror("module name is too long [%s.ko]\n", mod->name); 22284fd3e4efSWanlong Gao return 1; 22294fd3e4efSWanlong Gao } 22304fd3e4efSWanlong Gao 22314fd3e4efSWanlong Gao return 0; 22324fd3e4efSWanlong Gao } 22334fd3e4efSWanlong Gao 22345c3ead8cSSam Ravnborg /** 22355c3ead8cSSam Ravnborg * Header for the generated file 22365c3ead8cSSam Ravnborg **/ 22375c3ead8cSSam Ravnborg static void add_header(struct buffer *b, struct module *mod) 22381da177e4SLinus Torvalds { 22399afb719eSLaura Abbott buf_printf(b, "#include <linux/build-salt.h>\n"); 22401da177e4SLinus Torvalds buf_printf(b, "#include <linux/module.h>\n"); 22411da177e4SLinus Torvalds buf_printf(b, "#include <linux/vermagic.h>\n"); 22421da177e4SLinus Torvalds buf_printf(b, "#include <linux/compiler.h>\n"); 22431da177e4SLinus Torvalds buf_printf(b, "\n"); 22449afb719eSLaura Abbott buf_printf(b, "BUILD_SALT;\n"); 22459afb719eSLaura Abbott buf_printf(b, "\n"); 22461da177e4SLinus Torvalds buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); 22473e2e857fSKees Cook buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n"); 22481da177e4SLinus Torvalds buf_printf(b, "\n"); 2249e0f244c6SAndi Kleen buf_printf(b, "__visible struct module __this_module\n"); 2250a3d0cb04SMasahiro Yamada buf_printf(b, "__section(.gnu.linkonce.this_module) = {\n"); 22513c7ec94dSGreg Kroah-Hartman buf_printf(b, "\t.name = KBUILD_MODNAME,\n"); 22521da177e4SLinus Torvalds if (mod->has_init) 22533c7ec94dSGreg Kroah-Hartman buf_printf(b, "\t.init = init_module,\n"); 22541da177e4SLinus Torvalds if (mod->has_cleanup) 22551da177e4SLinus Torvalds buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n" 22563c7ec94dSGreg Kroah-Hartman "\t.exit = cleanup_module,\n" 22571da177e4SLinus Torvalds "#endif\n"); 22583c7ec94dSGreg Kroah-Hartman buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n"); 22591da177e4SLinus Torvalds buf_printf(b, "};\n"); 22601da177e4SLinus Torvalds } 22611da177e4SLinus Torvalds 22622449b8baSBen Hutchings static void add_intree_flag(struct buffer *b, int is_intree) 22632449b8baSBen Hutchings { 22642449b8baSBen Hutchings if (is_intree) 22652449b8baSBen Hutchings buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); 22662449b8baSBen Hutchings } 22672449b8baSBen Hutchings 2268caf7501aSAndi Kleen /* Cannot check for assembler */ 2269caf7501aSAndi Kleen static void add_retpoline(struct buffer *b) 2270caf7501aSAndi Kleen { 2271e4f35891SWANG Chao buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n"); 2272caf7501aSAndi Kleen buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n"); 2273caf7501aSAndi Kleen buf_printf(b, "#endif\n"); 2274caf7501aSAndi Kleen } 2275caf7501aSAndi Kleen 22765c725138STrevor Keith static void add_staging_flag(struct buffer *b, const char *name) 2277a9860bf0SGreg Kroah-Hartman { 2278d62c4765SMasahiro Yamada if (strstarts(name, "drivers/staging")) 2279a9860bf0SGreg Kroah-Hartman buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); 2280a9860bf0SGreg Kroah-Hartman } 2281a9860bf0SGreg Kroah-Hartman 22825c3ead8cSSam Ravnborg /** 22835c3ead8cSSam Ravnborg * Record CRCs for unresolved symbols 22845c3ead8cSSam Ravnborg **/ 2285c53ddacdSKirill Korotaev static int add_versions(struct buffer *b, struct module *mod) 22861da177e4SLinus Torvalds { 22871da177e4SLinus Torvalds struct symbol *s, *exp; 2288c53ddacdSKirill Korotaev int err = 0; 22891da177e4SLinus Torvalds 22901da177e4SLinus Torvalds for (s = mod->unres; s; s = s->next) { 22911da177e4SLinus Torvalds exp = find_symbol(s->name); 22923b415288SMasahiro Yamada if (!exp || exp->module == mod) 22931da177e4SLinus Torvalds continue; 22941da177e4SLinus Torvalds s->module = exp->module; 22951da177e4SLinus Torvalds s->crc_valid = exp->crc_valid; 22961da177e4SLinus Torvalds s->crc = exp->crc; 22971da177e4SLinus Torvalds } 22981da177e4SLinus Torvalds 22991da177e4SLinus Torvalds if (!modversions) 2300c53ddacdSKirill Korotaev return err; 23011da177e4SLinus Torvalds 23021da177e4SLinus Torvalds buf_printf(b, "\n"); 23031da177e4SLinus Torvalds buf_printf(b, "static const struct modversion_info ____versions[]\n"); 2304a3d0cb04SMasahiro Yamada buf_printf(b, "__used __section(__versions) = {\n"); 23051da177e4SLinus Torvalds 23061da177e4SLinus Torvalds for (s = mod->unres; s; s = s->next) { 2307df578e7dSSam Ravnborg if (!s->module) 23081da177e4SLinus Torvalds continue; 23091da177e4SLinus Torvalds if (!s->crc_valid) { 2310cb80514dSSam Ravnborg warn("\"%s\" [%s.ko] has no CRC!\n", 23111da177e4SLinus Torvalds s->name, mod->name); 23121da177e4SLinus Torvalds continue; 23131da177e4SLinus Torvalds } 23145cfb203aSTakashi Iwai if (strlen(s->name) >= MODULE_NAME_LEN) { 23155cfb203aSTakashi Iwai merror("too long symbol \"%s\" [%s.ko]\n", 23165cfb203aSTakashi Iwai s->name, mod->name); 23175cfb203aSTakashi Iwai err = 1; 23185cfb203aSTakashi Iwai break; 23195cfb203aSTakashi Iwai } 2320b2c5cdcfSMasahiro Yamada buf_printf(b, "\t{ %#8x, \"%s\" },\n", 2321a4b6a77bSJames Hogan s->crc, s->name); 23221da177e4SLinus Torvalds } 23231da177e4SLinus Torvalds 23241da177e4SLinus Torvalds buf_printf(b, "};\n"); 2325c53ddacdSKirill Korotaev 2326c53ddacdSKirill Korotaev return err; 23271da177e4SLinus Torvalds } 23281da177e4SLinus Torvalds 2329d2665ca8SMasahiro Yamada static void add_depends(struct buffer *b, struct module *mod) 23301da177e4SLinus Torvalds { 23311da177e4SLinus Torvalds struct symbol *s; 23321da177e4SLinus Torvalds int first = 1; 23331da177e4SLinus Torvalds 2334d2665ca8SMasahiro Yamada /* Clear ->seen flag of modules that own symbols needed by this. */ 2335d2665ca8SMasahiro Yamada for (s = mod->unres; s; s = s->next) 2336d2665ca8SMasahiro Yamada if (s->module) 2337d2665ca8SMasahiro Yamada s->module->seen = is_vmlinux(s->module->name); 23381da177e4SLinus Torvalds 23391da177e4SLinus Torvalds buf_printf(b, "\n"); 23406df7e1ecSMasahiro Yamada buf_printf(b, "MODULE_INFO(depends, \""); 23411da177e4SLinus Torvalds for (s = mod->unres; s; s = s->next) { 2342a61b2dfdSSam Ravnborg const char *p; 23431da177e4SLinus Torvalds if (!s->module) 23441da177e4SLinus Torvalds continue; 23451da177e4SLinus Torvalds 23461da177e4SLinus Torvalds if (s->module->seen) 23471da177e4SLinus Torvalds continue; 23481da177e4SLinus Torvalds 23491da177e4SLinus Torvalds s->module->seen = 1; 2350df578e7dSSam Ravnborg p = strrchr(s->module->name, '/'); 2351df578e7dSSam Ravnborg if (p) 2352a61b2dfdSSam Ravnborg p++; 2353a61b2dfdSSam Ravnborg else 2354a61b2dfdSSam Ravnborg p = s->module->name; 2355a61b2dfdSSam Ravnborg buf_printf(b, "%s%s", first ? "" : ",", p); 23561da177e4SLinus Torvalds first = 0; 23571da177e4SLinus Torvalds } 23586df7e1ecSMasahiro Yamada buf_printf(b, "\");\n"); 23591da177e4SLinus Torvalds } 23601da177e4SLinus Torvalds 23615c3ead8cSSam Ravnborg static void add_srcversion(struct buffer *b, struct module *mod) 23621da177e4SLinus Torvalds { 23631da177e4SLinus Torvalds if (mod->srcversion[0]) { 23641da177e4SLinus Torvalds buf_printf(b, "\n"); 23651da177e4SLinus Torvalds buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n", 23661da177e4SLinus Torvalds mod->srcversion); 23671da177e4SLinus Torvalds } 23681da177e4SLinus Torvalds } 23691da177e4SLinus Torvalds 23705c3ead8cSSam Ravnborg static void write_if_changed(struct buffer *b, const char *fname) 23711da177e4SLinus Torvalds { 23721da177e4SLinus Torvalds char *tmp; 23731da177e4SLinus Torvalds FILE *file; 23741da177e4SLinus Torvalds struct stat st; 23751da177e4SLinus Torvalds 23761da177e4SLinus Torvalds file = fopen(fname, "r"); 23771da177e4SLinus Torvalds if (!file) 23781da177e4SLinus Torvalds goto write; 23791da177e4SLinus Torvalds 23801da177e4SLinus Torvalds if (fstat(fileno(file), &st) < 0) 23811da177e4SLinus Torvalds goto close_write; 23821da177e4SLinus Torvalds 23831da177e4SLinus Torvalds if (st.st_size != b->pos) 23841da177e4SLinus Torvalds goto close_write; 23851da177e4SLinus Torvalds 23861da177e4SLinus Torvalds tmp = NOFAIL(malloc(b->pos)); 23871da177e4SLinus Torvalds if (fread(tmp, 1, b->pos, file) != b->pos) 23881da177e4SLinus Torvalds goto free_write; 23891da177e4SLinus Torvalds 23901da177e4SLinus Torvalds if (memcmp(tmp, b->p, b->pos) != 0) 23911da177e4SLinus Torvalds goto free_write; 23921da177e4SLinus Torvalds 23931da177e4SLinus Torvalds free(tmp); 23941da177e4SLinus Torvalds fclose(file); 23951da177e4SLinus Torvalds return; 23961da177e4SLinus Torvalds 23971da177e4SLinus Torvalds free_write: 23981da177e4SLinus Torvalds free(tmp); 23991da177e4SLinus Torvalds close_write: 24001da177e4SLinus Torvalds fclose(file); 24011da177e4SLinus Torvalds write: 24021da177e4SLinus Torvalds file = fopen(fname, "w"); 24031da177e4SLinus Torvalds if (!file) { 24041da177e4SLinus Torvalds perror(fname); 24051da177e4SLinus Torvalds exit(1); 24061da177e4SLinus Torvalds } 24071da177e4SLinus Torvalds if (fwrite(b->p, 1, b->pos, file) != b->pos) { 24081da177e4SLinus Torvalds perror(fname); 24091da177e4SLinus Torvalds exit(1); 24101da177e4SLinus Torvalds } 24111da177e4SLinus Torvalds fclose(file); 24121da177e4SLinus Torvalds } 24131da177e4SLinus Torvalds 2414bd5cbcedSRam Pai /* parse Module.symvers file. line format: 2415534b89a9SSam Ravnborg * 0x12345678<tab>symbol<tab>module[[<tab>export]<tab>something] 2416bd5cbcedSRam Pai **/ 2417040fcc81SSam Ravnborg static void read_dump(const char *fname, unsigned int kernel) 24181da177e4SLinus Torvalds { 24191da177e4SLinus Torvalds unsigned long size, pos = 0; 24201da177e4SLinus Torvalds void *file = grab_file(fname, &size); 24211da177e4SLinus Torvalds char *line; 24221da177e4SLinus Torvalds 24231da177e4SLinus Torvalds if (!file) 24241da177e4SLinus Torvalds /* No symbol versions, silently ignore */ 24251da177e4SLinus Torvalds return; 24261da177e4SLinus Torvalds 24271da177e4SLinus Torvalds while ((line = get_next_line(&pos, file, size))) { 2428cb9b55d2SMatthias Maennich char *symname, *namespace, *modname, *d, *export, *end; 24291da177e4SLinus Torvalds unsigned int crc; 24301da177e4SLinus Torvalds struct module *mod; 2431040fcc81SSam Ravnborg struct symbol *s; 24321da177e4SLinus Torvalds 24331da177e4SLinus Torvalds if (!(symname = strchr(line, '\t'))) 24341da177e4SLinus Torvalds goto fail; 24351da177e4SLinus Torvalds *symname++ = '\0'; 2436cb9b55d2SMatthias Maennich if (!(namespace = strchr(symname, '\t'))) 2437cb9b55d2SMatthias Maennich goto fail; 2438cb9b55d2SMatthias Maennich *namespace++ = '\0'; 2439cb9b55d2SMatthias Maennich if (!(modname = strchr(namespace, '\t'))) 24401da177e4SLinus Torvalds goto fail; 24411da177e4SLinus Torvalds *modname++ = '\0'; 24429ac545b0SLaurent Riffard if ((export = strchr(modname, '\t')) != NULL) 2443bd5cbcedSRam Pai *export++ = '\0'; 2444534b89a9SSam Ravnborg if (export && ((end = strchr(export, '\t')) != NULL)) 2445534b89a9SSam Ravnborg *end = '\0'; 24461da177e4SLinus Torvalds crc = strtoul(line, &d, 16); 24471da177e4SLinus Torvalds if (*symname == '\0' || *modname == '\0' || *d != '\0') 24481da177e4SLinus Torvalds goto fail; 2449df578e7dSSam Ravnborg mod = find_module(modname); 2450df578e7dSSam Ravnborg if (!mod) { 2451df578e7dSSam Ravnborg if (is_vmlinux(modname)) 24521da177e4SLinus Torvalds have_vmlinux = 1; 24530fa3a88cSJan Beulich mod = new_module(modname); 24541da177e4SLinus Torvalds mod->skip = 1; 24551da177e4SLinus Torvalds } 2456cb9b55d2SMatthias Maennich s = sym_add_exported(symname, namespace, mod, 2457cb9b55d2SMatthias Maennich export_no(export)); 2458040fcc81SSam Ravnborg s->kernel = kernel; 24598e70c458SSam Ravnborg s->preloaded = 1; 246015bfc234SDenis Efremov s->is_static = 0; 2461bd5cbcedSRam Pai sym_update_crc(symname, mod, crc, export_no(export)); 24621da177e4SLinus Torvalds } 24632ee41e62SChristian Engelmayer release_file(file, size); 24641da177e4SLinus Torvalds return; 24651da177e4SLinus Torvalds fail: 24662ee41e62SChristian Engelmayer release_file(file, size); 24671da177e4SLinus Torvalds fatal("parse error in symbol dump file\n"); 24681da177e4SLinus Torvalds } 24691da177e4SLinus Torvalds 2470040fcc81SSam Ravnborg /* For normal builds always dump all symbols. 2471040fcc81SSam Ravnborg * For external modules only dump symbols 2472040fcc81SSam Ravnborg * that are not read from kernel Module.symvers. 2473040fcc81SSam Ravnborg **/ 2474040fcc81SSam Ravnborg static int dump_sym(struct symbol *sym) 2475040fcc81SSam Ravnborg { 2476040fcc81SSam Ravnborg if (!external_module) 2477040fcc81SSam Ravnborg return 1; 2478040fcc81SSam Ravnborg if (sym->vmlinux || sym->kernel) 2479040fcc81SSam Ravnborg return 0; 2480040fcc81SSam Ravnborg return 1; 2481040fcc81SSam Ravnborg } 2482040fcc81SSam Ravnborg 24835c3ead8cSSam Ravnborg static void write_dump(const char *fname) 24841da177e4SLinus Torvalds { 24851da177e4SLinus Torvalds struct buffer buf = { }; 24861da177e4SLinus Torvalds struct symbol *symbol; 2487cb9b55d2SMatthias Maennich const char *namespace; 24881da177e4SLinus Torvalds int n; 24891da177e4SLinus Torvalds 24901da177e4SLinus Torvalds for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { 24911da177e4SLinus Torvalds symbol = symbolhash[n]; 24921da177e4SLinus Torvalds while (symbol) { 2493cb9b55d2SMatthias Maennich if (dump_sym(symbol)) { 2494cb9b55d2SMatthias Maennich namespace = symbol->namespace; 2495cb9b55d2SMatthias Maennich buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", 2496040fcc81SSam Ravnborg symbol->crc, symbol->name, 2497cb9b55d2SMatthias Maennich namespace ? namespace : "", 2498bd5cbcedSRam Pai symbol->module->name, 2499bd5cbcedSRam Pai export_str(symbol->export)); 2500cb9b55d2SMatthias Maennich } 25011da177e4SLinus Torvalds symbol = symbol->next; 25021da177e4SLinus Torvalds } 25031da177e4SLinus Torvalds } 25041da177e4SLinus Torvalds write_if_changed(&buf, fname); 2505c7d47f26SHeinrich Schuchardt free(buf.p); 25061da177e4SLinus Torvalds } 25071da177e4SLinus Torvalds 25081d082773SMatthias Maennich static void write_namespace_deps_files(void) 25091d082773SMatthias Maennich { 25101d082773SMatthias Maennich struct module *mod; 25111d082773SMatthias Maennich struct namespace_list *ns; 25121d082773SMatthias Maennich struct buffer ns_deps_buf = {}; 25131d082773SMatthias Maennich 25141d082773SMatthias Maennich for (mod = modules; mod; mod = mod->next) { 25151d082773SMatthias Maennich char fname[PATH_MAX]; 25161d082773SMatthias Maennich 25171d082773SMatthias Maennich if (mod->skip) 25181d082773SMatthias Maennich continue; 25191d082773SMatthias Maennich 25201d082773SMatthias Maennich ns_deps_buf.pos = 0; 25211d082773SMatthias Maennich 25221d082773SMatthias Maennich for (ns = mod->required_namespaces; ns; ns = ns->next) 25231d082773SMatthias Maennich buf_printf(&ns_deps_buf, "%s\n", ns->namespace); 25241d082773SMatthias Maennich 25251d082773SMatthias Maennich if (ns_deps_buf.pos == 0) 25261d082773SMatthias Maennich continue; 25271d082773SMatthias Maennich 25281d082773SMatthias Maennich sprintf(fname, "%s.ns_deps", mod->name); 25291d082773SMatthias Maennich write_if_changed(&ns_deps_buf, fname); 25301d082773SMatthias Maennich } 25311d082773SMatthias Maennich } 25321d082773SMatthias Maennich 25332d04b5aeSRichard Hacker struct ext_sym_list { 25342d04b5aeSRichard Hacker struct ext_sym_list *next; 25352d04b5aeSRichard Hacker const char *file; 25362d04b5aeSRichard Hacker }; 25372d04b5aeSRichard Hacker 25385c3ead8cSSam Ravnborg int main(int argc, char **argv) 25391da177e4SLinus Torvalds { 25401da177e4SLinus Torvalds struct module *mod; 25411da177e4SLinus Torvalds struct buffer buf = { }; 2542040fcc81SSam Ravnborg char *kernel_read = NULL, *module_read = NULL; 2543712f9b46SRusty Russell char *dump_write = NULL, *files_source = NULL; 25441da177e4SLinus Torvalds int opt; 2545c53ddacdSKirill Korotaev int err; 254615bfc234SDenis Efremov int n; 25472d04b5aeSRichard Hacker struct ext_sym_list *extsym_iter; 25482d04b5aeSRichard Hacker struct ext_sym_list *extsym_start = NULL; 25491da177e4SLinus Torvalds 25501d082773SMatthias Maennich while ((opt = getopt(argc, argv, "i:I:e:mnsT:o:awEd")) != -1) { 25511da177e4SLinus Torvalds switch (opt) { 25521da177e4SLinus Torvalds case 'i': 2553040fcc81SSam Ravnborg kernel_read = optarg; 2554040fcc81SSam Ravnborg break; 2555040fcc81SSam Ravnborg case 'I': 2556040fcc81SSam Ravnborg module_read = optarg; 2557040fcc81SSam Ravnborg external_module = 1; 25581da177e4SLinus Torvalds break; 25592d04b5aeSRichard Hacker case 'e': 25602d04b5aeSRichard Hacker external_module = 1; 25612d04b5aeSRichard Hacker extsym_iter = 25622d04b5aeSRichard Hacker NOFAIL(malloc(sizeof(*extsym_iter))); 25632d04b5aeSRichard Hacker extsym_iter->next = extsym_start; 25642d04b5aeSRichard Hacker extsym_iter->file = optarg; 25652d04b5aeSRichard Hacker extsym_start = extsym_iter; 25662d04b5aeSRichard Hacker break; 25671da177e4SLinus Torvalds case 'm': 25681da177e4SLinus Torvalds modversions = 1; 25691da177e4SLinus Torvalds break; 2570eed380f3SGuenter Roeck case 'n': 2571eed380f3SGuenter Roeck ignore_missing_files = 1; 2572eed380f3SGuenter Roeck break; 25731da177e4SLinus Torvalds case 'o': 25741da177e4SLinus Torvalds dump_write = optarg; 25751da177e4SLinus Torvalds break; 25761da177e4SLinus Torvalds case 'a': 25771da177e4SLinus Torvalds all_versions = 1; 25781da177e4SLinus Torvalds break; 25798d8d8289SSam Ravnborg case 's': 25808d8d8289SSam Ravnborg vmlinux_section_warnings = 0; 25818d8d8289SSam Ravnborg break; 2582712f9b46SRusty Russell case 'T': 2583712f9b46SRusty Russell files_source = optarg; 2584712f9b46SRusty Russell break; 2585c53ddacdSKirill Korotaev case 'w': 2586c53ddacdSKirill Korotaev warn_unresolved = 1; 2587c53ddacdSKirill Korotaev break; 258847490ec1SNicolas Boichat case 'E': 258947490ec1SNicolas Boichat sec_mismatch_fatal = 1; 259047490ec1SNicolas Boichat break; 25911d082773SMatthias Maennich case 'd': 25921d082773SMatthias Maennich write_namespace_deps = 1; 25931d082773SMatthias Maennich break; 25941da177e4SLinus Torvalds default: 25951da177e4SLinus Torvalds exit(1); 25961da177e4SLinus Torvalds } 25971da177e4SLinus Torvalds } 25981da177e4SLinus Torvalds 2599040fcc81SSam Ravnborg if (kernel_read) 2600040fcc81SSam Ravnborg read_dump(kernel_read, 1); 2601040fcc81SSam Ravnborg if (module_read) 2602040fcc81SSam Ravnborg read_dump(module_read, 0); 26032d04b5aeSRichard Hacker while (extsym_start) { 26042d04b5aeSRichard Hacker read_dump(extsym_start->file, 0); 26052d04b5aeSRichard Hacker extsym_iter = extsym_start->next; 26062d04b5aeSRichard Hacker free(extsym_start); 26072d04b5aeSRichard Hacker extsym_start = extsym_iter; 26082d04b5aeSRichard Hacker } 26091da177e4SLinus Torvalds 2610df578e7dSSam Ravnborg while (optind < argc) 26111da177e4SLinus Torvalds read_symbols(argv[optind++]); 26121da177e4SLinus Torvalds 2613712f9b46SRusty Russell if (files_source) 2614712f9b46SRusty Russell read_symbols_from_files(files_source); 2615712f9b46SRusty Russell 2616c53ddacdSKirill Korotaev err = 0; 2617c53ddacdSKirill Korotaev 2618b817f6feSSam Ravnborg for (mod = modules; mod; mod = mod->next) { 2619d93e1719SMathias Krause char fname[PATH_MAX]; 2620666ab414SAndi Kleen 2621b817f6feSSam Ravnborg if (mod->skip) 2622b817f6feSSam Ravnborg continue; 26231da177e4SLinus Torvalds 26241da177e4SLinus Torvalds buf.pos = 0; 26251da177e4SLinus Torvalds 26264fd3e4efSWanlong Gao err |= check_modname_len(mod); 26273b415288SMasahiro Yamada err |= check_exports(mod); 26281d082773SMatthias Maennich if (write_namespace_deps) 26291d082773SMatthias Maennich continue; 26301d082773SMatthias Maennich 26311da177e4SLinus Torvalds add_header(&buf, mod); 26322449b8baSBen Hutchings add_intree_flag(&buf, !external_module); 2633caf7501aSAndi Kleen add_retpoline(&buf); 2634a9860bf0SGreg Kroah-Hartman add_staging_flag(&buf, mod->name); 2635c53ddacdSKirill Korotaev err |= add_versions(&buf, mod); 2636d2665ca8SMasahiro Yamada add_depends(&buf, mod); 26371da177e4SLinus Torvalds add_moddevtable(&buf, mod); 26381da177e4SLinus Torvalds add_srcversion(&buf, mod); 26391da177e4SLinus Torvalds 26401da177e4SLinus Torvalds sprintf(fname, "%s.mod.c", mod->name); 26411da177e4SLinus Torvalds write_if_changed(&buf, fname); 26421da177e4SLinus Torvalds } 26431d082773SMatthias Maennich 26441d082773SMatthias Maennich if (write_namespace_deps) { 26451d082773SMatthias Maennich write_namespace_deps_files(); 26461d082773SMatthias Maennich return 0; 26471d082773SMatthias Maennich } 26481d082773SMatthias Maennich 26491da177e4SLinus Torvalds if (dump_write) 26501da177e4SLinus Torvalds write_dump(dump_write); 265146c7dd56SMasahiro Yamada if (sec_mismatch_count && sec_mismatch_fatal) 265247490ec1SNicolas Boichat fatal("modpost: Section mismatches detected.\n" 265347490ec1SNicolas Boichat "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n"); 265415bfc234SDenis Efremov for (n = 0; n < SYMBOL_HASH_SIZE; n++) { 2655*47346e96SMasahiro Yamada struct symbol *s; 265615bfc234SDenis Efremov 2657*47346e96SMasahiro Yamada for (s = symbolhash[n]; s; s = s->next) { 2658*47346e96SMasahiro Yamada /* 2659*47346e96SMasahiro Yamada * Do not check "vmlinux". This avoids the same warnings 2660*47346e96SMasahiro Yamada * shown twice, and false-positives for ARCH=um. 2661*47346e96SMasahiro Yamada */ 2662*47346e96SMasahiro Yamada if (is_vmlinux(s->module->name) && !s->module->is_dot_o) 2663*47346e96SMasahiro Yamada continue; 2664*47346e96SMasahiro Yamada 266515bfc234SDenis Efremov if (s->is_static) 266615bfc234SDenis Efremov warn("\"%s\" [%s] is a static %s\n", 266715bfc234SDenis Efremov s->name, s->module->name, 266815bfc234SDenis Efremov export_str(s->export)); 266915bfc234SDenis Efremov } 267015bfc234SDenis Efremov } 267115bfc234SDenis Efremov 2672c7d47f26SHeinrich Schuchardt free(buf.p); 26731da177e4SLinus Torvalds 2674c53ddacdSKirill Korotaev return err; 26751da177e4SLinus Torvalds } 2676