Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / scripts / mod / modpost.c
index 0b92ddf..d0f86ed 100644 (file)
@@ -487,22 +487,24 @@ static int strrcmp(const char *s, const char *sub)
  *   atsym   =__param*
  *
  * Pattern 2:
- *   Many drivers utilise a *_driver container with references to
+ *   Many drivers utilise a *driver container with references to
  *   add, remove, probe functions etc.
  *   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
+ *   tosec   = .init.text | .exit.text | .init.data
  *   fromsec = .data
- *   atsym = *_driver, *_ops, *_probe, *probe_one
+ *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one
  **/
 static int secref_whitelist(const char *tosec, const char *fromsec,
-                         const char *atsym)
+                           const char *atsym)
 {
        int f1 = 1, f2 = 1;
        const char **s;
        const char *pat2sym[] = {
-               "_driver",
+               "driver",
+               "_template", /* scsi uses *_template a lot */
+               "_sht",      /* scsi also used *_sht to some extent */
                "_ops",
                "_probe",
                "_probe_one",
@@ -522,7 +524,8 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
 
        /* Check for pattern 2 */
        if ((strcmp(tosec, ".init.text") != 0) &&
-           (strcmp(tosec, ".exit.text") != 0))
+           (strcmp(tosec, ".exit.text") != 0) &&
+           (strcmp(tosec, ".init.data") != 0))
                f2 = 0;
        if (strcmp(fromsec, ".data") != 0)
                f2 = 0;
@@ -658,7 +661,7 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
                warn("%s - Section mismatch: reference to %s:%s from %s "
                     "before '%s' (at offset -0x%llx)\n",
                     modname, secname, refsymname, fromsec,
-                    elf->strtab + before->st_name,
+                    elf->strtab + after->st_name,
                     (long long)r.r_offset);
        } else {
                warn("%s - Section mismatch: reference to %s:%s from %s "
@@ -694,29 +697,79 @@ static void check_sec_ref(struct module *mod, const char *modname,
 
        /* Walk through all sections */
        for (i = 0; i < hdr->e_shnum; i++) {
-               Elf_Rela *rela;
-               Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
-               Elf_Rela *stop  = (void*)start + sechdrs[i].sh_size;
-               const char *name = secstrings + sechdrs[i].sh_name +
-                                               strlen(".rela");
+               const char *name = secstrings + sechdrs[i].sh_name;
+               const char *secname;
+               Elf_Rela r;
+               unsigned int r_sym;
                /* We want to process only relocation sections and not .init */
-               if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA))
-                       continue;
+               if (sechdrs[i].sh_type == SHT_RELA) {
+                       Elf_Rela *rela;
+                       Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset;
+                       Elf_Rela *stop  = (void*)start + sechdrs[i].sh_size;
+                       name += strlen(".rela");
+                       if (section_ref_ok(name))
+                               continue;
 
-               for (rela = start; rela < stop; rela++) {
-                       Elf_Rela r;
-                       const char *secname;
-                       r.r_offset = TO_NATIVE(rela->r_offset);
-                       r.r_info   = TO_NATIVE(rela->r_info);
-                       r.r_addend = TO_NATIVE(rela->r_addend);
-                       sym = elf->symtab_start + ELF_R_SYM(r.r_info);
-                       /* Skip special sections */
-                       if (sym->st_shndx >= SHN_LORESERVE)
+                       for (rela = start; rela < stop; rela++) {
+                               r.r_offset = TO_NATIVE(rela->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+                               if (hdr->e_machine == EM_MIPS) {
+                                       r_sym = ELF64_MIPS_R_SYM(rela->r_info);
+                                       r_sym = TO_NATIVE(r_sym);
+                               } else {
+                                       r.r_info = TO_NATIVE(rela->r_info);
+                                       r_sym = ELF_R_SYM(r.r_info);
+                               }
+#else
+                               r.r_info = TO_NATIVE(rela->r_info);
+                               r_sym = ELF_R_SYM(r.r_info);
+#endif
+                               r.r_addend = TO_NATIVE(rela->r_addend);
+                               sym = elf->symtab_start + r_sym;
+                               /* Skip special sections */
+                               if (sym->st_shndx >= SHN_LORESERVE)
+                                       continue;
+
+                               secname = secstrings +
+                                       sechdrs[sym->st_shndx].sh_name;
+                               if (section(secname))
+                                       warn_sec_mismatch(modname, name,
+                                                         elf, sym, r);
+                       }
+               } else if (sechdrs[i].sh_type == SHT_REL) {
+                       Elf_Rel *rel;
+                       Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset;
+                       Elf_Rel *stop  = (void*)start + sechdrs[i].sh_size;
+                       name += strlen(".rel");
+                       if (section_ref_ok(name))
                                continue;
 
-                       secname = secstrings + sechdrs[sym->st_shndx].sh_name;
-                       if (section(secname))
-                               warn_sec_mismatch(modname, name, elf, sym, r);
+                       for (rel = start; rel < stop; rel++) {
+                               r.r_offset = TO_NATIVE(rel->r_offset);
+#if KERNEL_ELFCLASS == ELFCLASS64
+                               if (hdr->e_machine == EM_MIPS) {
+                                       r_sym = ELF64_MIPS_R_SYM(rel->r_info);
+                                       r_sym = TO_NATIVE(r_sym);
+                               } else {
+                                       r.r_info = TO_NATIVE(rel->r_info);
+                                       r_sym = ELF_R_SYM(r.r_info);
+                               }
+#else
+                               r.r_info = TO_NATIVE(rel->r_info);
+                               r_sym = ELF_R_SYM(r.r_info);
+#endif
+                               r.r_addend = 0;
+                               sym = elf->symtab_start + r_sym;
+                               /* Skip special sections */
+                               if (sym->st_shndx >= SHN_LORESERVE)
+                                       continue;
+
+                               secname = secstrings +
+                                       sechdrs[sym->st_shndx].sh_name;
+                               if (section(secname))
+                                       warn_sec_mismatch(modname, name,
+                                                         elf, sym, r);
+                       }
                }
        }
 }
@@ -820,6 +873,7 @@ static int exit_section(const char *name)
  * For our future {in}sanity, add a comment that this is the ppc .opd
  * section, not the ia64 .opd section.
  * ia64 .opd should not point to discarded sections.
+ * [.rodata] like for .init.text we ignore .rodata references -same reason
  **/
 static int exit_section_ref_ok(const char *name)
 {
@@ -829,6 +883,7 @@ static int exit_section_ref_ok(const char *name)
                ".exit.text",
                ".exit.data",
                ".init.text",
+               ".rodata",
                ".opd", /* See comment [OPD] */
                ".toc1",  /* used by ppc64 */
                ".altinstructions",