s2io: Fixes in updating skb->truesize and code cleanup.
[powerpc.git] / scripts / mod / modpost.c
index dfde0e8..2aa4762 100644 (file)
@@ -23,6 +23,8 @@ int have_vmlinux = 0;
 static int all_versions = 0;
 /* If we are modposting external module set to 1 */
 static int external_module = 0;
+/* Only warn about unresolved symbols */
+static int warn_unresolved = 0;
 /* How a symbol is exported */
 enum export {
        export_plain,      export_unused,     export_gpl,
@@ -580,9 +582,19 @@ static int strrcmp(const char *s, const char *sub)
  *   tosec   = .init.text | .exit.text | .init.data
  *   fromsec = .data
  *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
+ *
+ * Pattern 3:
+ *   Some symbols belong to init section but still it is ok to reference
+ *   these from non-init sections as these symbols don't have any memory
+ *   allocated for them and symbol address and value are same. So even
+ *   if init section is freed, its ok to reference those symbols.
+ *   For ex. symbols marking the init section boundaries.
+ *   This pattern is identified by
+ *   refsymname = __init_begin, _sinittext, _einittext
  **/
-static int secref_whitelist(const char *tosec, const char *fromsec,
-                           const char *atsym)
+static int secref_whitelist(const char *modname, const char *tosec,
+                           const char *fromsec, const char *atsym,
+                           const char *refsymname)
 {
        int f1 = 1, f2 = 1;
        const char **s;
@@ -593,6 +605,14 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
                "_ops",
                "_probe",
                "_probe_one",
+               "_console",
+               NULL
+       };
+
+       const char *pat3refsym[] = {
+               "__init_begin",
+               "_sinittext",
+               "_einittext",
                NULL
        };
 
@@ -618,8 +638,21 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
        for (s = pat2sym; *s; s++)
                if (strrcmp(atsym, *s) == 0)
                        f1 = 1;
+       if (f1 && f2)
+               return 1;
+
+       /* Whitelist all references from .pci_fixup section if vmlinux */
+       if (is_vmlinux(modname)) {
+               if ((strcmp(fromsec, ".pci_fixup") == 0) &&
+                   (strcmp(tosec, ".init.text") == 0))
+               return 1;
 
-       return f1 && f2;
+               /* Check for pattern 3 */
+               for (s = pat3refsym; *s; s++)
+                       if (strcmp(refsymname, *s) == 0)
+                               return 1;
+       }
+       return 0;
 }
 
 /**
@@ -726,7 +759,8 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
 
        /* check whitelist - we may ignore it */
        if (before &&
-           secref_whitelist(secname, fromsec, elf->strtab + before->st_name))
+           secref_whitelist(modname, secname, fromsec,
+                            elf->strtab + before->st_name, refsymname))
                return;
 
        if (before && after) {
@@ -900,6 +934,7 @@ static int init_section_ref_ok(const char *name)
                ".toc1",  /* used by ppc64 */
                ".stab",
                ".rodata",
+               ".parainstructions",
                ".text.lock",
                "__bug_table", /* used by powerpc for BUG() */
                ".pci_fixup_header",
@@ -910,6 +945,8 @@ static int init_section_ref_ok(const char *name)
                ".fixup",
                ".smp_locks",
                ".plt",  /* seen on ARCH=um build on x86_64. Harmless */
+               "__ftr_fixup",          /* powerpc cpu feature fixup */
+               "__fw_ftr_fixup",       /* powerpc firmware feature fixup */
                NULL
        };
        /* Start of section names */
@@ -918,6 +955,7 @@ static int init_section_ref_ok(const char *name)
                ".altinstructions",
                ".eh_frame",
                ".debug",
+               ".parainstructions",
                NULL
        };
        /* part of section name */
@@ -982,6 +1020,7 @@ static int exit_section_ref_ok(const char *name)
                "__bug_table", /* used by powerpc for BUG() */
                ".exitcall.exit",
                ".eh_frame",
+               ".parainstructions",
                ".stab",
                "__ex_table",
                ".fixup",
@@ -1187,16 +1226,19 @@ static void add_header(struct buffer *b, struct module *mod)
 /**
  * Record CRCs for unresolved symbols
  **/
-static void add_versions(struct buffer *b, struct module *mod)
+static int add_versions(struct buffer *b, struct module *mod)
 {
        struct symbol *s, *exp;
+       int err = 0;
 
        for (s = mod->unres; s; s = s->next) {
                exp = find_symbol(s->name);
                if (!exp || exp->module == mod) {
-                       if (have_vmlinux && !s->weak)
+                       if (have_vmlinux && !s->weak) {
                                warn("\"%s\" [%s.ko] undefined!\n",
                                     s->name, mod->name);
+                               err = warn_unresolved ? 0 : 1;
+                       }
                        continue;
                }
                s->module = exp->module;
@@ -1205,7 +1247,7 @@ static void add_versions(struct buffer *b, struct module *mod)
        }
 
        if (!modversions)
-               return;
+               return err;
 
        buf_printf(b, "\n");
        buf_printf(b, "static const struct modversion_info ____versions[]\n");
@@ -1225,6 +1267,8 @@ static void add_versions(struct buffer *b, struct module *mod)
        }
 
        buf_printf(b, "};\n");
+
+       return err;
 }
 
 static void add_depends(struct buffer *b, struct module *mod,
@@ -1402,8 +1446,9 @@ int main(int argc, char **argv)
        char *kernel_read = NULL, *module_read = NULL;
        char *dump_write = NULL;
        int opt;
+       int err;
 
-       while ((opt = getopt(argc, argv, "i:I:mo:a")) != -1) {
+       while ((opt = getopt(argc, argv, "i:I:mo:aw")) != -1) {
                switch(opt) {
                        case 'i':
                                kernel_read = optarg;
@@ -1421,6 +1466,9 @@ int main(int argc, char **argv)
                        case 'a':
                                all_versions = 1;
                                break;
+                       case 'w':
+                               warn_unresolved = 1;
+                               break;
                        default:
                                exit(1);
                }
@@ -1441,6 +1489,8 @@ int main(int argc, char **argv)
                check_exports(mod);
        }
 
+       err = 0;
+
        for (mod = modules; mod; mod = mod->next) {
                if (mod->skip)
                        continue;
@@ -1448,7 +1498,7 @@ int main(int argc, char **argv)
                buf.pos = 0;
 
                add_header(&buf, mod);
-               add_versions(&buf, mod);
+               err |= add_versions(&buf, mod);
                add_depends(&buf, mod, modules);
                add_moddevtable(&buf, mod);
                add_srcversion(&buf, mod);
@@ -1460,5 +1510,5 @@ int main(int argc, char **argv)
        if (dump_write)
                write_dump(dump_write);
 
-       return 0;
+       return err;
 }