kbuild: remove hardcoded apic_es7000 from modpost
[safe/jmp/linux-2.6] / scripts / mod / modpost.c
index 628f393..1921c43 100644 (file)
@@ -374,6 +374,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
        hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
        hdr->e_shnum    = TO_NATIVE(hdr->e_shnum);
        hdr->e_machine  = TO_NATIVE(hdr->e_machine);
+       hdr->e_type     = TO_NATIVE(hdr->e_type);
        sechdrs = (void *)hdr + hdr->e_shoff;
        info->sechdrs = sechdrs;
 
@@ -384,6 +385,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
                sechdrs[i].sh_size   = TO_NATIVE(sechdrs[i].sh_size);
                sechdrs[i].sh_link   = TO_NATIVE(sechdrs[i].sh_link);
                sechdrs[i].sh_name   = TO_NATIVE(sechdrs[i].sh_name);
+               sechdrs[i].sh_info   = TO_NATIVE(sechdrs[i].sh_info);
+               sechdrs[i].sh_addr   = TO_NATIVE(sechdrs[i].sh_addr);
        }
        /* Find symbol table. */
        for (i = 1; i < hdr->e_shnum; i++) {
@@ -582,6 +585,12 @@ static int strrcmp(const char *s, const char *sub)
 
 /**
  * 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
+ *
  * Pattern 1:
  *   If a module parameter is declared __initdata and permissions=0
  *   then this is legal despite the warning generated.
@@ -603,14 +612,10 @@ static int strrcmp(const char *s, const char *sub)
  *   atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console
  *
  * Pattern 3:
- *   Whitelist all references from .pci_fixup* section to .init.text
- *   This is part of the PCI init when built-in
- *
- * Pattern 4:
  *   Whitelist all refereces from .text.head to .init.data
  *   Whitelist all refereces from .text.head to .init.text
  *
- * Pattern 5:
+ * Pattern 4:
  *   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
@@ -619,15 +624,7 @@ static int strrcmp(const char *s, const char *sub)
  *   This pattern is identified by
  *   refsymname = __init_begin, _sinittext, _einittext
  *
- * Pattern 6:
- *   During the early init phase we have references from .init.text to
- *   .text we have an intended section mismatch - do not warn about it.
- *   See kernel_init() in init/main.c
- *   tosec   = .init.text
- *   fromsec = .text
- *   atsym = kernel_init
- *
- * Pattern 7:
+ * Pattern 5:
  *  Logos used in drivers/video/logo reside in __initdata but the
  *  funtion that references them are EXPORT_SYMBOL() so cannot be
  *  marker __init. So we whitelist them here.
@@ -635,13 +632,6 @@ static int strrcmp(const char *s, const char *sub)
  *  tosec      = .init.data
  *  fromsec    = .text*
  *  refsymname = logo_
- *
- * Pattern 8:
- *  Symbols contained in .paravirtprobe may safely reference .init.text.
- *  The pattern is:
- *  tosec   = .init.text
- *  fromsec  = .paravirtprobe
- *
  **/
 static int secref_whitelist(const char *modname, const char *tosec,
                            const char *fromsec, const char *atsym,
@@ -667,6 +657,11 @@ static int secref_whitelist(const char *modname, const char *tosec,
                NULL
        };
 
+       /* Check for pattern 0 */
+       if ((strcmp(fromsec, ".text.init.refok") == 0) ||
+           (strcmp(fromsec, ".data.init.refok") == 0))
+               return 1;
+
        /* Check for pattern 1 */
        if (strcmp(tosec, ".init.data") != 0)
                f1 = 0;
@@ -693,38 +688,22 @@ static int secref_whitelist(const char *modname, const char *tosec,
                return 1;
 
        /* Check for pattern 3 */
-       if ((strncmp(fromsec, ".pci_fixup", strlen(".pci_fixup")) == 0) &&
-           (strcmp(tosec, ".init.text") == 0))
-       return 1;
-
-       /* Check for pattern 4 */
        if ((strcmp(fromsec, ".text.head") == 0) &&
                ((strcmp(tosec, ".init.data") == 0) ||
                (strcmp(tosec, ".init.text") == 0)))
        return 1;
 
-       /* Check for pattern 5 */
+       /* Check for pattern 4 */
        for (s = pat3refsym; *s; s++)
                if (strcmp(refsymname, *s) == 0)
                        return 1;
 
-       /* Check for pattern 6 */
-       if ((strcmp(tosec, ".init.text") == 0) &&
-           (strcmp(fromsec, ".text") == 0) &&
-           (strcmp(refsymname, "kernel_init") == 0))
-               return 1;
-
-       /* Check for pattern 7 */
+       /* Check for pattern 5 */
        if ((strcmp(tosec, ".init.data") == 0) &&
            (strncmp(fromsec, ".text", strlen(".text")) == 0) &&
            (strncmp(refsymname, "logo_", strlen("logo_")) == 0))
                return 1;
 
-       /* Check for pattern 8 */
-       if ((strcmp(tosec, ".init.text") == 0) &&
-           (strcmp(fromsec, ".paravirtprobe") == 0))
-               return 1;
-
        return 0;
 }
 
@@ -745,6 +724,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
        for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
                if (sym->st_shndx != relsym->st_shndx)
                        continue;
+               if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
+                       continue;
                if (sym->st_value == addr)
                        return sym;
        }
@@ -857,30 +838,101 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
                return;
 
        if (before && after) {
-               warn("%s - Section mismatch: reference to %s:%s from %s "
-                    "between '%s' (at offset 0x%llx) and '%s'\n",
-                    modname, secname, refsymname, fromsec,
+               warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
+                    "(between '%s' and '%s')\n",
+                    modname, fromsec, (unsigned long long)r.r_offset,
+                    secname, refsymname,
                     elf->strtab + before->st_name,
-                    (long long)r.r_offset,
                     elf->strtab + after->st_name);
        } else if (before) {
-               warn("%s - Section mismatch: reference to %s:%s from %s "
-                    "after '%s' (at offset 0x%llx)\n",
-                    modname, secname, refsymname, fromsec,
-                    elf->strtab + before->st_name,
-                    (long long)r.r_offset);
+               warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
+                    "(after '%s')\n",
+                    modname, fromsec, (unsigned long long)r.r_offset,
+                    secname, refsymname,
+                    elf->strtab + before->st_name);
        } else if (after) {
-               warn("%s - Section mismatch: reference to %s:%s from %s "
+               warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
                     "before '%s' (at offset -0x%llx)\n",
-                    modname, secname, refsymname, fromsec,
-                    elf->strtab + after->st_name,
-                    (long long)r.r_offset);
+                    modname, fromsec, (unsigned long long)r.r_offset,
+                    secname, refsymname,
+                    elf->strtab + after->st_name);
        } else {
-               warn("%s - Section mismatch: reference to %s:%s from %s "
-                    "(offset 0x%llx)\n",
-                    modname, secname, fromsec, refsymname,
-                    (long long)r.r_offset);
+               warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",
+                    modname, fromsec, (unsigned long long)r.r_offset,
+                    secname, refsymname);
+       }
+}
+
+static unsigned int *reloc_location(struct elf_info *elf,
+                                          int rsection, Elf_Rela *r)
+{
+       Elf_Shdr *sechdrs = elf->sechdrs;
+       int section = sechdrs[rsection].sh_info;
+
+       return (void *)elf->hdr + sechdrs[section].sh_offset +
+               (r->r_offset - sechdrs[section].sh_addr);
+}
+
+static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
+{
+       unsigned int r_typ = ELF_R_TYPE(r->r_info);
+       unsigned int *location = reloc_location(elf, rsection, r);
+
+       switch (r_typ) {
+       case R_386_32:
+               r->r_addend = TO_NATIVE(*location);
+               break;
+       case R_386_PC32:
+               r->r_addend = TO_NATIVE(*location) + 4;
+               /* For CONFIG_RELOCATABLE=y */
+               if (elf->hdr->e_type == ET_EXEC)
+                       r->r_addend += r->r_offset;
+               break;
+       }
+       return 0;
+}
+
+static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
+{
+       unsigned int r_typ = ELF_R_TYPE(r->r_info);
+
+       switch (r_typ) {
+       case R_ARM_ABS32:
+               /* From ARM ABI: (S + A) | T */
+               r->r_addend = (int)(long)(elf->symtab_start + ELF_R_SYM(r->r_info));
+               break;
+       case R_ARM_PC24:
+               /* From ARM ABI: ((S + A) | T) - P */
+               r->r_addend = (int)(long)(elf->hdr + elf->sechdrs[rsection].sh_offset +
+                                         (r->r_offset - elf->sechdrs[rsection].sh_addr));
+               break;
+       default:
+               return 1;
+       }
+       return 0;
+}
+
+static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
+{
+       unsigned int r_typ = ELF_R_TYPE(r->r_info);
+       unsigned int *location = reloc_location(elf, rsection, r);
+       unsigned int inst;
+
+       if (r_typ == R_MIPS_HI16)
+               return 1;       /* skip this */
+       inst = TO_NATIVE(*location);
+       switch (r_typ) {
+       case R_MIPS_LO16:
+               r->r_addend = inst & 0xffff;
+               break;
+       case R_MIPS_26:
+               r->r_addend = (inst & 0x03ffffff) << 2;
+               break;
+       case R_MIPS_32:
+               r->r_addend = inst;
+               break;
        }
+       return 0;
 }
 
 /**
@@ -926,8 +978,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
                                r.r_offset = TO_NATIVE(rela->r_offset);
 #if KERNEL_ELFCLASS == ELFCLASS64
                                if (hdr->e_machine == EM_MIPS) {
+                                       unsigned int r_typ;
                                        r_sym = ELF64_MIPS_R_SYM(rela->r_info);
                                        r_sym = TO_NATIVE(r_sym);
+                                       r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
+                                       r.r_info = ELF64_R_INFO(r_sym, r_typ);
                                } else {
                                        r.r_info = TO_NATIVE(rela->r_info);
                                        r_sym = ELF_R_SYM(r.r_info);
@@ -960,8 +1015,11 @@ static void check_sec_ref(struct module *mod, const char *modname,
                                r.r_offset = TO_NATIVE(rel->r_offset);
 #if KERNEL_ELFCLASS == ELFCLASS64
                                if (hdr->e_machine == EM_MIPS) {
+                                       unsigned int r_typ;
                                        r_sym = ELF64_MIPS_R_SYM(rel->r_info);
                                        r_sym = TO_NATIVE(r_sym);
+                                       r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
+                                       r.r_info = ELF64_R_INFO(r_sym, r_typ);
                                } else {
                                        r.r_info = TO_NATIVE(rel->r_info);
                                        r_sym = ELF_R_SYM(r.r_info);
@@ -971,6 +1029,20 @@ static void check_sec_ref(struct module *mod, const char *modname,
                                r_sym = ELF_R_SYM(r.r_info);
 #endif
                                r.r_addend = 0;
+                               switch (hdr->e_machine) {
+                               case EM_386:
+                                       if (addend_386_rel(elf, i, &r))
+                                               continue;
+                                       break;
+                               case EM_ARM:
+                                       if(addend_arm_rel(elf, i, &r))
+                                               continue;
+                                       break;
+                               case EM_MIPS:
+                                       if (addend_mips_rel(elf, i, &r))
+                                               continue;
+                                       break;
+                               }
                                sym = elf->symtab_start + r_sym;
                                /* Skip special sections */
                                if (sym->st_shndx >= SHN_LORESERVE)
@@ -986,6 +1058,63 @@ static void check_sec_ref(struct module *mod, const char *modname,
        }
 }
 
+/*
+ * Identify sections from which references to either a
+ * .init or a .exit section is OK.
+ *
+ * [OPD] Keith Ownes <kaos@sgi.com> commented:
+ * 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 initexit_section_ref_ok(const char *name)
+{
+       const char **s;
+       /* Absolute section names */
+       const char *namelist1[] = {
+               "__bug_table",          /* used by powerpc for BUG() */
+               "__ex_table",
+               ".altinstructions",
+               ".cranges",             /* used by sh64 */
+               ".fixup",
+               ".machvec",             /* ia64 + powerpc uses these */
+               ".machine.desc",
+               ".opd",                 /* See comment [OPD] */
+               ".parainstructions",
+               ".pdr",
+               ".plt",                 /* seen on ARCH=um build on x86_64. Harmless */
+               ".smp_locks",
+               ".stab",
+               NULL
+       };
+       /* Start of section names */
+       const char *namelist2[] = {
+               ".debug",
+               ".eh_frame",
+               ".note",                /* ignore ELF notes - may contain anything */
+               ".got",                 /* powerpc - global offset table */
+               ".toc",                 /* powerpc - table of contents */
+               NULL
+       };
+       /* part of section name */
+       const char *namelist3 [] = {
+               ".unwind",  /* Sample: IA_64.unwind.exit.text */
+               NULL
+       };
+
+       for (s = namelist1; *s; s++)
+               if (strcmp(*s, name) == 0)
+                       return 1;
+       for (s = namelist2; *s; s++)
+               if (strncmp(*s, name, strlen(*s)) == 0)
+                       return 1;
+       for (s = namelist3; *s; s++)
+               if (strstr(name, *s) != NULL)
+                       return 1;
+       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
@@ -1002,7 +1131,7 @@ static int init_section(const char *name)
        return 0;
 }
 
-/**
+/*
  * Identify sections from which references to a .init section is OK.
  *
  * Unfortunately references to read only data that referenced .init
@@ -1016,47 +1145,30 @@ static int init_section(const char *name)
  *
  * where vgacon_startup is __init.  If you want to wade through the false
  * positives, take out the check for rodata.
- **/
+ */
 static int init_section_ref_ok(const char *name)
 {
        const char **s;
        /* Absolute section names */
        const char *namelist1[] = {
-               ".init",
-               ".opd",   /* see comment [OPD] at exit_section_ref_ok() */
-               ".toc1",  /* used by ppc64 */
-               ".stab",
-               ".data.rel.ro", /* used by parisc64 */
-               ".parainstructions",
-               ".text.lock",
-               "__bug_table", /* used by powerpc for BUG() */
-               ".pci_fixup_header",
-               ".pci_fixup_final",
-               ".pdr",
-               "__param",
-               "__ex_table",
-               ".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 */
+               "__param",
+               ".data.rel.ro",         /* used by parisc64 */
+               ".init",
+               ".text.lock",
                NULL
        };
        /* Start of section names */
        const char *namelist2[] = {
                ".init.",
-               ".altinstructions",
-               ".eh_frame",
-               ".debug",
-               ".parainstructions",
+               ".pci_fixup",
                ".rodata",
                NULL
        };
-       /* part of section name */
-       const char *namelist3 [] = {
-               ".unwind",  /* sample: IA_64.unwind.init.text */
-               NULL
-       };
+
+       if (initexit_section_ref_ok(name))
+               return 1;
 
        for (s = namelist1; *s; s++)
                if (strcmp(*s, name) == 0)
@@ -1064,9 +1176,10 @@ static int init_section_ref_ok(const char *name)
        for (s = namelist2; *s; s++)
                if (strncmp(*s, name, strlen(*s)) == 0)
                        return 1;
-       for (s = namelist3; *s; s++)
-               if (strstr(name, *s) != NULL)
-                       return 1;
+
+       /* If section name ends with ".init" we allow references
+        * as is the case with .initcallN.init, .early_param.init, .taglist.init etc
+        */
        if (strrcmp(name, ".init") == 0)
                return 1;
        return 0;
@@ -1091,57 +1204,25 @@ static int exit_section(const char *name)
 
 /*
  * Identify sections from which references to a .exit section is OK.
- *
- * [OPD] Keith Ownes <kaos@sgi.com> commented:
- * 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)
 {
        const char **s;
        /* Absolute section names */
        const char *namelist1[] = {
-               ".exit.text",
                ".exit.data",
-               ".init.text",
-               ".rodata",
-               ".opd", /* See comment [OPD] */
-               ".toc1",  /* used by ppc64 */
-               ".altinstructions",
-               ".pdr",
-               "__bug_table", /* used by powerpc for BUG() */
+               ".exit.text",
                ".exitcall.exit",
-               ".eh_frame",
-               ".parainstructions",
-               ".stab",
-               "__ex_table",
-               ".fixup",
-               ".smp_locks",
-               ".plt",  /* seen on ARCH=um build on x86_64. Harmless */
-               NULL
-       };
-       /* Start of section names */
-       const char *namelist2[] = {
-               ".debug",
-               NULL
-       };
-       /* part of section name */
-       const char *namelist3 [] = {
-               ".unwind",  /* Sample: IA_64.unwind.exit.text */
+               ".rodata",
                NULL
        };
 
+       if (initexit_section_ref_ok(name))
+               return 1;
+
        for (s = namelist1; *s; s++)
                if (strcmp(*s, name) == 0)
                        return 1;
-       for (s = namelist2; *s; s++)
-               if (strncmp(*s, name, strlen(*s)) == 0)
-                       return 1;
-       for (s = namelist3; *s; s++)
-               if (strstr(name, *s) != NULL)
-                       return 1;
        return 0;
 }
 
@@ -1315,6 +1396,7 @@ static void add_header(struct buffer *b, struct module *mod)
                buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
                              " .exit = cleanup_module,\n"
                              "#endif\n");
+       buf_printf(b, " .arch = MODULE_ARCH_INIT,\n");
        buf_printf(b, "};\n");
 }