Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
[~shefty/rdma-dev.git] / scripts / mod / modpost.c
index 859bee4972e95fac48e9b63a670795f01e6c22f7..33122ca04e7cd99cfb1be6bb4a5c62fd66efe51b 100644 (file)
@@ -14,6 +14,7 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <ctype.h>
+#include <string.h>
 #include "modpost.h"
 #include "../../include/generated/autoconf.h"
 #include "../../include/linux/license.h"
@@ -789,6 +790,7 @@ static const char *section_white_list[] =
 {
        ".comment*",
        ".debug*",
+       ".GCC-command-line",    /* mn10300 */
        ".mdebug*",        /* alpha, score, mips etc. */
        ".pdr",            /* alpha, score, mips etc. */
        ".stab*",
@@ -1033,6 +1035,13 @@ static const struct sectioncheck *section_mismatch(
  *   fromsec = .data*
  *   atsym   =__param*
  *
+ * Pattern 1a:
+ *   module_param_call() ops can refer to __init set function if permissions=0
+ *   The pattern is identified by:
+ *   tosec   = .init.text
+ *   fromsec = .data*
+ *   atsym   = __param_ops_*
+ *
  * Pattern 2:
  *   Many drivers utilise a *driver container with references to
  *   add, remove, probe functions etc.
@@ -1067,6 +1076,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
            (strncmp(fromsym, "__param", strlen("__param")) == 0))
                return 0;
 
+       /* Check for pattern 1a */
+       if (strcmp(tosec, ".init.text") == 0 &&
+           match(fromsec, data_sections) &&
+           (strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0))
+               return 0;
+
        /* Check for pattern 2 */
        if (match(tosec, init_exit_sections) &&
            match(fromsec, data_sections) &&
@@ -1220,7 +1235,7 @@ static char *sec2annotation(const char *s)
                        strcat(p, " ");
                return r;
        } else {
-               return "";
+               return strdup("");
        }
 }
 
@@ -1248,6 +1263,8 @@ static void report_sec_mismatch(const char *modname,
 {
        const char *from, *from_p;
        const char *to, *to_p;
+       char *prl_from;
+       char *prl_to;
 
        switch (from_is_func) {
        case 0: from = "variable"; from_p = "";   break;
@@ -1271,16 +1288,21 @@ static void report_sec_mismatch(const char *modname,
 
        switch (mismatch->mismatch) {
        case TEXT_TO_ANY_INIT:
+               prl_from = sec2annotation(fromsec);
+               prl_to = sec2annotation(tosec);
                fprintf(stderr,
                "The function %s%s() references\n"
                "the %s %s%s%s.\n"
                "This is often because %s lacks a %s\n"
                "annotation or the annotation of %s is wrong.\n",
-               sec2annotation(fromsec), fromsym,
-               to, sec2annotation(tosec), tosym, to_p,
-               fromsym, sec2annotation(tosec), tosym);
+               prl_from, fromsym,
+               to, prl_to, tosym, to_p,
+               fromsym, prl_to, tosym);
+               free(prl_from);
+               free(prl_to);
                break;
        case DATA_TO_ANY_INIT: {
+               prl_to = sec2annotation(tosec);
                const char *const *s = mismatch->symbol_white_list;
                fprintf(stderr,
                "The variable %s references\n"
@@ -1288,20 +1310,24 @@ static void report_sec_mismatch(const char *modname,
                "If the reference is valid then annotate the\n"
                "variable with __init* or __refdata (see linux/init.h) "
                "or name the variable:\n",
-               fromsym, to, sec2annotation(tosec), tosym, to_p);
+               fromsym, to, prl_to, tosym, to_p);
                while (*s)
                        fprintf(stderr, "%s, ", *s++);
                fprintf(stderr, "\n");
+               free(prl_to);
                break;
        }
        case TEXT_TO_ANY_EXIT:
+               prl_to = sec2annotation(tosec);
                fprintf(stderr,
                "The function %s() references a %s in an exit section.\n"
                "Often the %s %s%s has valid usage outside the exit section\n"
                "and the fix is to remove the %sannotation of %s.\n",
-               fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
+               fromsym, to, to, tosym, to_p, prl_to, tosym);
+               free(prl_to);
                break;
        case DATA_TO_ANY_EXIT: {
+               prl_to = sec2annotation(tosec);
                const char *const *s = mismatch->symbol_white_list;
                fprintf(stderr,
                "The variable %s references\n"
@@ -1309,24 +1335,31 @@ static void report_sec_mismatch(const char *modname,
                "If the reference is valid then annotate the\n"
                "variable with __exit* (see linux/init.h) or "
                "name the variable:\n",
-               fromsym, to, sec2annotation(tosec), tosym, to_p);
+               fromsym, to, prl_to, tosym, to_p);
                while (*s)
                        fprintf(stderr, "%s, ", *s++);
                fprintf(stderr, "\n");
+               free(prl_to);
                break;
        }
        case XXXINIT_TO_SOME_INIT:
        case XXXEXIT_TO_SOME_EXIT:
+               prl_from = sec2annotation(fromsec);
+               prl_to = sec2annotation(tosec);
                fprintf(stderr,
                "The %s %s%s%s references\n"
                "a %s %s%s%s.\n"
                "If %s is only used by %s then\n"
                "annotate %s with a matching annotation.\n",
-               from, sec2annotation(fromsec), fromsym, from_p,
-               to, sec2annotation(tosec), tosym, to_p,
+               from, prl_from, fromsym, from_p,
+               to, prl_to, tosym, to_p,
                tosym, fromsym, tosym);
+               free(prl_from);
+               free(prl_to);
                break;
        case ANY_INIT_TO_ANY_EXIT:
+               prl_from = sec2annotation(fromsec);
+               prl_to = sec2annotation(tosec);
                fprintf(stderr,
                "The %s %s%s%s references\n"
                "a %s %s%s%s.\n"
@@ -1335,11 +1368,15 @@ static void report_sec_mismatch(const char *modname,
                "uses functionality in the exit path.\n"
                "The fix is often to remove the %sannotation of\n"
                "%s%s so it may be used outside an exit section.\n",
-               from, sec2annotation(fromsec), fromsym, from_p,
-               to, sec2annotation(tosec), tosym, to_p,
-               sec2annotation(tosec), tosym, to_p);
+               from, prl_from, fromsym, from_p,
+               to, prl_to, tosym, to_p,
+               prl_to, tosym, to_p);
+               free(prl_from);
+               free(prl_to);
                break;
        case ANY_EXIT_TO_ANY_INIT:
+               prl_from = sec2annotation(fromsec);
+               prl_to = sec2annotation(tosec);
                fprintf(stderr,
                "The %s %s%s%s references\n"
                "a %s %s%s%s.\n"
@@ -1348,16 +1385,20 @@ static void report_sec_mismatch(const char *modname,
                "uses functionality in the init path.\n"
                "The fix is often to remove the %sannotation of\n"
                "%s%s so it may be used outside an init section.\n",
-               from, sec2annotation(fromsec), fromsym, from_p,
-               to, sec2annotation(tosec), tosym, to_p,
-               sec2annotation(tosec), tosym, to_p);
+               from, prl_from, fromsym, from_p,
+               to, prl_to, tosym, to_p,
+               prl_to, tosym, to_p);
+               free(prl_from);
+               free(prl_to);
                break;
        case EXPORT_TO_INIT_EXIT:
+               prl_to = sec2annotation(tosec);
                fprintf(stderr,
                "The symbol %s is exported and annotated %s\n"
                "Fix this by removing the %sannotation of %s "
                "or drop the export.\n",
-               tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
+               tosym, prl_to, prl_to, tosym);
+               free(prl_to);
                break;
        }
        fprintf(stderr, "\n");