]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - scripts/mod/modpost.c
Merge tag 'pci-v4.21-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[linux.git] / scripts / mod / modpost.c
index 0d998c54564dfdc5793faa968f72e8e985bce6c8..0de2fb2366402a13c7f42e02c6f3912d180585d3 100644 (file)
@@ -1163,6 +1163,14 @@ static const struct sectioncheck *section_mismatch(
  *   fromsec = text section
  *   refsymname = *.constprop.*
  *
+ * Pattern 6:
+ *   Hide section mismatch warnings for ELF local symbols.  The goal
+ *   is to eliminate false positive modpost warnings caused by
+ *   compiler-generated ELF local symbol names such as ".LANCHOR1".
+ *   Autogenerated symbol names bypass modpost's "Pattern 2"
+ *   whitelisting, which relies on pattern-matching against symbol
+ *   names to work.  (One situation where gcc can autogenerate ELF
+ *   local symbols is when "-fsection-anchors" is used.)
  **/
 static int secref_whitelist(const struct sectioncheck *mismatch,
                            const char *fromsec, const char *fromsym,
@@ -1201,9 +1209,37 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
            match(fromsym, optim_symbols))
                return 0;
 
+       /* Check for pattern 6 */
+       if (strstarts(fromsym, ".L"))
+               return 0;
+
        return 1;
 }
 
+static inline int is_arm_mapping_symbol(const char *str)
+{
+       return str[0] == '$' && strchr("axtd", str[1])
+              && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+       const char *name = elf->strtab + sym->st_name;
+
+       if (!name || !strlen(name))
+               return 0;
+       return !is_arm_mapping_symbol(name);
+}
+
 /**
  * Find symbol based on relocation record info.
  * In some cases the symbol supplied is a valid symbol so
@@ -1229,6 +1265,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
                        continue;
                if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
                        continue;
+               if (!is_valid_name(elf, sym))
+                       continue;
                if (sym->st_value == addr)
                        return sym;
                /* Find a symbol nearby - addr are maybe negative */
@@ -1247,30 +1285,6 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
                return NULL;
 }
 
-static inline int is_arm_mapping_symbol(const char *str)
-{
-       return str[0] == '$' && strchr("axtd", str[1])
-              && (str[2] == '\0' || str[2] == '.');
-}
-
-/*
- * If there's no name there, ignore it; likewise, ignore it if it's
- * one of the magic symbols emitted used by current ARM tools.
- *
- * Otherwise if find_symbols_between() returns those symbols, they'll
- * fail the whitelist tests and cause lots of false alarms ... fixable
- * only by merging __exit and __init sections into __text, bloating
- * the kernel (which is especially evil on embedded platforms).
- */
-static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
-{
-       const char *name = elf->strtab + sym->st_name;
-
-       if (!name || !strlen(name))
-               return 0;
-       return !is_arm_mapping_symbol(name);
-}
-
 /*
  * Find symbols before or equal addr and after addr - in the section sec.
  * If we find two symbols with equal offset prefer one with a valid name.
@@ -2083,15 +2097,27 @@ static void check_for_unused(enum export exp, const char *m, const char *s)
        }
 }
 
-static void check_exports(struct module *mod)
+static int check_exports(struct module *mod)
 {
        struct symbol *s, *exp;
+       int err = 0;
 
        for (s = mod->unres; s; s = s->next) {
                const char *basename;
                exp = find_symbol(s->name);
-               if (!exp || exp->module == mod)
+               if (!exp || exp->module == mod) {
+                       if (have_vmlinux && !s->weak) {
+                               if (warn_unresolved) {
+                                       warn("\"%s\" [%s.ko] undefined!\n",
+                                            s->name, mod->name);
+                               } else {
+                                       merror("\"%s\" [%s.ko] undefined!\n",
+                                              s->name, mod->name);
+                                       err = 1;
+                               }
+                       }
                        continue;
+               }
                basename = strrchr(mod->name, '/');
                if (basename)
                        basename++;
@@ -2101,6 +2127,8 @@ static void check_exports(struct module *mod)
                        check_for_gpl_usage(exp->export, basename, exp->name);
                check_for_unused(exp->export, basename, exp->name);
        }
+
+       return err;
 }
 
 static int check_modname_len(struct module *mod)
@@ -2178,19 +2206,8 @@ static int add_versions(struct buffer *b, struct module *mod)
 
        for (s = mod->unres; s; s = s->next) {
                exp = find_symbol(s->name);
-               if (!exp || exp->module == mod) {
-                       if (have_vmlinux && !s->weak) {
-                               if (warn_unresolved) {
-                                       warn("\"%s\" [%s.ko] undefined!\n",
-                                            s->name, mod->name);
-                               } else {
-                                       merror("\"%s\" [%s.ko] undefined!\n",
-                                              s->name, mod->name);
-                                       err = 1;
-                               }
-                       }
+               if (!exp || exp->module == mod)
                        continue;
-               }
                s->module = exp->module;
                s->crc_valid = exp->crc_valid;
                s->crc = exp->crc;
@@ -2227,15 +2244,15 @@ static int add_versions(struct buffer *b, struct module *mod)
        return err;
 }
 
-static void add_depends(struct buffer *b, struct module *mod,
-                       struct module *modules)
+static void add_depends(struct buffer *b, struct module *mod)
 {
        struct symbol *s;
-       struct module *m;
        int first = 1;
 
-       for (m = modules; m; m = m->next)
-               m->seen = is_vmlinux(m->name);
+       /* Clear ->seen flag of modules that own symbols needed by this. */
+       for (s = mod->unres; s; s = s->next)
+               if (s->module)
+                       s->module->seen = is_vmlinux(s->module->name);
 
        buf_printf(b, "\n");
        buf_printf(b, "static const char __module_depends[]\n");
@@ -2416,7 +2433,7 @@ int main(int argc, char **argv)
        struct ext_sym_list *extsym_iter;
        struct ext_sym_list *extsym_start = NULL;
 
-       while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:E")) != -1) {
+       while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awE")) != -1) {
                switch (opt) {
                case 'i':
                        kernel_read = optarg;
@@ -2482,12 +2499,6 @@ int main(int argc, char **argv)
        if (files_source)
                read_symbols_from_files(files_source);
 
-       for (mod = modules; mod; mod = mod->next) {
-               if (mod->skip)
-                       continue;
-               check_exports(mod);
-       }
-
        err = 0;
 
        for (mod = modules; mod; mod = mod->next) {
@@ -2499,12 +2510,13 @@ int main(int argc, char **argv)
                buf.pos = 0;
 
                err |= check_modname_len(mod);
+               err |= check_exports(mod);
                add_header(&buf, mod);
                add_intree_flag(&buf, !external_module);
                add_retpoline(&buf);
                add_staging_flag(&buf, mod->name);
                err |= add_versions(&buf, mod);
-               add_depends(&buf, mod, modules);
+               add_depends(&buf, mod);
                add_moddevtable(&buf, mod);
                add_srcversion(&buf, mod);