Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
[safe/jmp/linux-2.6] / scripts / mod / modpost.c
index 87e3ee5..2ef9a19 100644 (file)
@@ -381,6 +381,12 @@ static int parse_elf(struct elf_info *info, const char *filename)
        sechdrs = (void *)hdr + hdr->e_shoff;
        info->sechdrs = sechdrs;
 
+       /* Check if file offset is correct */
+       if (hdr->e_shoff > info->size) {
+               fatal("section header offset=%u in file '%s' is bigger then filesize=%lu\n", hdr->e_shoff, filename, info->size);
+               return 0;
+       }
+
        /* Fix endianness in section headers */
        for (i = 0; i < hdr->e_shnum; i++) {
                sechdrs[i].sh_type   = TO_NATIVE(sechdrs[i].sh_type);
@@ -586,13 +592,61 @@ static int strrcmp(const char *s, const char *sub)
         return memcmp(s + slen - sublen, sub, sublen);
 }
 
+/*
+ * Functions used only during module init is marked __init and is stored in
+ * a .init.text section. Likewise data is marked __initdata and stored in
+ * a .init.data section.
+ * If this section is one of these sections return 1
+ * See include/linux/init.h for the details
+ */
+static int init_section(const char *name)
+{
+       if (strcmp(name, ".init") == 0)
+               return 1;
+       if (strncmp(name, ".init.", strlen(".init.")) == 0)
+               return 1;
+       return 0;
+}
+
+/*
+ * Functions used only during module exit is marked __exit and is stored in
+ * a .exit.text section. Likewise data is marked __exitdata and stored in
+ * a .exit.data section.
+ * If this section is one of these sections return 1
+ * See include/linux/init.h for the details
+ **/
+static int exit_section(const char *name)
+{
+       if (strcmp(name, ".exit.text") == 0)
+               return 1;
+       if (strcmp(name, ".exit.data") == 0)
+               return 1;
+       return 0;
+
+}
+
+/*
+ * Data sections are named like this:
+ * .data | .data.rel | .data.rel.*
+ * Return 1 if the specified section is a data section
+ */
+static int data_section(const char *name)
+{
+       if ((strcmp(name, ".data") == 0) ||
+           (strcmp(name, ".data.rel") == 0) ||
+           (strncmp(name, ".data.rel.", strlen(".data.rel.")) == 0))
+               return 1;
+       else
+               return 0;
+}
+
 /**
  * Whitelist to allow certain references to pass with no warning.
  *
  * Pattern 0:
  *   Do not warn if funtion/data are marked with __init_refok/__initdata_refok.
  *   The pattern is identified by:
- *   fromsec = .text.init.refok | .data.init.refok
+ *   fromsec = .text.init.refok* | .data.init.refok*
  *
  * Pattern 1:
  *   If a module parameter is declared __initdata and permissions=0
@@ -610,8 +664,8 @@ static int strrcmp(const char *s, const char *sub)
  *   These functions may often be marked __init and we do not want to
  *   warn here.
  *   the pattern is identified by:
- *   tosec   = .init.text | .exit.text | .init.data
- *   fromsec = .data | .data.rel | .data.rel.*
+ *   tosec   = init or exit section
+ *   fromsec = data section
  *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console, *_timer
  *
  * Pattern 3:
@@ -627,12 +681,18 @@ static int strrcmp(const char *s, const char *sub)
  *   This pattern is identified by
  *   refsymname = __init_begin, _sinittext, _einittext
  *
+ * Pattern 5:
+ *   Xtensa uses literal sections for constants that are accessed PC-relative.
+ *   Literal sections may safely reference their text sections.
+ *   (Note that the name for the literal section omits any trailing '.text')
+ *   tosec = <section>[.text]
+ *   fromsec = <section>.literal
  **/
 static int secref_whitelist(const char *modname, const char *tosec,
                            const char *fromsec, const char *atsym,
                            const char *refsymname)
 {
-       int f1 = 1, f2 = 1;
+       int len;
        const char **s;
        const char *pat2sym[] = {
                "driver",
@@ -654,36 +714,22 @@ static int secref_whitelist(const char *modname, const char *tosec,
        };
 
        /* Check for pattern 0 */
-       if ((strcmp(fromsec, ".text.init.refok") == 0) ||
-           (strcmp(fromsec, ".data.init.refok") == 0))
+       if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) ||
+           (strncmp(fromsec, ".exit.text.refok", strlen(".exit.text.refok")) == 0) ||
+           (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0))
                return 1;
 
        /* Check for pattern 1 */
-       if (strcmp(tosec, ".init.data") != 0)
-               f1 = 0;
-       if (strncmp(fromsec, ".data", strlen(".data")) != 0)
-               f1 = 0;
-       if (strncmp(atsym, "__param", strlen("__param")) != 0)
-               f1 = 0;
-
-       if (f1)
-               return f1;
+       if ((strcmp(tosec, ".init.data") == 0) &&
+           (strncmp(fromsec, ".data", strlen(".data")) == 0) &&
+           (strncmp(atsym, "__param", strlen("__param")) == 0))
+               return 1;
 
        /* Check for pattern 2 */
-       if ((strcmp(tosec, ".init.text") != 0) &&
-           (strcmp(tosec, ".exit.text") != 0) &&
-           (strcmp(tosec, ".init.data") != 0))
-               f2 = 0;
-       if ((strcmp(fromsec, ".data") != 0) &&
-           (strcmp(fromsec, ".data.rel") != 0) &&
-           (strncmp(fromsec, ".data.rel.", strlen(".data.rel.")) != 0))
-               f2 = 0;
-
-       for (s = pat2sym; *s; s++)
-               if (strrcmp(atsym, *s) == 0)
-                       f1 = 1;
-       if (f1 && f2)
-               return 1;
+       if ((init_section(tosec) || exit_section(tosec)) && data_section(fromsec))
+               for (s = pat2sym; *s; s++)
+                       if (strrcmp(atsym, *s) == 0)
+                               return 1;
 
        /* Check for pattern 3 */
        if ((strcmp(fromsec, ".text.head") == 0) &&
@@ -696,6 +742,15 @@ static int secref_whitelist(const char *modname, const char *tosec,
                if (strcmp(refsymname, *s) == 0)
                        return 1;
 
+       /* Check for pattern 5 */
+       if (strrcmp(tosec, ".text") == 0)
+               len = strlen(tosec) - strlen(".text");
+       else
+               len = strlen(tosec);
+       if ((strncmp(tosec, fromsec, len) == 0) && (strlen(fromsec) > len) &&
+           (strcmp(fromsec + len, ".literal") == 0))
+               return 1;
+
        return 0;
 }
 
@@ -824,9 +879,9 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
                refsymname = elf->strtab + refsym->st_name;
 
        /* check whitelist - we may ignore it */
-       if (before &&
-           secref_whitelist(modname, secname, fromsec,
-                            elf->strtab + before->st_name, refsymname))
+       if (secref_whitelist(modname, secname, fromsec,
+                            before ? elf->strtab + before->st_name : "",
+                            refsymname))
                return;
 
        if (before && after) {
@@ -1073,12 +1128,15 @@ static int initexit_section_ref_ok(const char *name)
                ".machvec",             /* ia64 + powerpc uses these */
                ".machine.desc",
                ".opd",                 /* See comment [OPD] */
+               "__dbe_table",
                ".parainstructions",
                ".pdr",
                ".plt",                 /* seen on ARCH=um build on x86_64. Harmless */
                ".smp_locks",
                ".stab",
                ".m68k_fixup",
+               ".xt.prop",             /* xtensa informational section */
+               ".xt.lit",              /* xtensa informational section */
                NULL
        };
        /* Start of section names */
@@ -1108,21 +1166,6 @@ static int initexit_section_ref_ok(const char *name)
        return 0;
 }
 
-/**
- * Functions used only during module init is marked __init and is stored in
- * a .init.text section. Likewise data is marked __initdata and stored in
- * a .init.data section.
- * If this section is one of these sections return 1
- * See include/linux/init.h for the details
- **/
-static int init_section(const char *name)
-{
-       if (strcmp(name, ".init") == 0)
-               return 1;
-       if (strncmp(name, ".init.", strlen(".init.")) == 0)
-               return 1;
-       return 0;
-}
 
 /*
  * Identify sections from which references to a .init section is OK.
@@ -1180,23 +1223,6 @@ static int init_section_ref_ok(const char *name)
 }
 
 /*
- * Functions used only during module exit is marked __exit and is stored in
- * a .exit.text section. Likewise data is marked __exitdata and stored in
- * a .exit.data section.
- * If this section is one of these sections return 1
- * See include/linux/init.h for the details
- **/
-static int exit_section(const char *name)
-{
-       if (strcmp(name, ".exit.text") == 0)
-               return 1;
-       if (strcmp(name, ".exit.data") == 0)
-               return 1;
-       return 0;
-
-}
-
-/*
  * Identify sections from which references to a .exit section is OK.
  */
 static int exit_section_ref_ok(const char *name)