kbuild: simplified warning report in modpost
[linux-2.6.git] / scripts / mod / modpost.c
index e4099cd..0a80aca 100644 (file)
@@ -607,7 +607,10 @@ static int strrcmp(const char *s, const char *sub)
 
 static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
 {
-       return elf->strtab + sym->st_name;
+       if (sym)
+               return elf->strtab + sym->st_name;
+       else
+               return "";
 }
 
 static const char *sec_name(struct elf_info *elf, int shndx)
@@ -812,7 +815,6 @@ static int section_mismatch(const char *fromsec, const char *tosec)
        return 0;
 }
 
-
 /**
  * Whitelist to allow certain references to pass with no warning.
  *
@@ -856,36 +858,35 @@ static int section_mismatch(const char *fromsec, const char *tosec)
  *   refsymname = __init_begin, _sinittext, _einittext
  *
  **/
-static int secref_whitelist(const char *modname, const char *tosec,
-                           const char *fromsec, const char *atsym,
-                           const char *refsymname)
+static int secref_whitelist(const char *fromsec, const char *fromsym,
+                           const char *tosec, const char *tosym)
 {
        /* Check for pattern 0 */
        if (match(fromsec, initref_sections))
-               return 1;
+               return 0;
 
        /* Check for pattern 1 */
        if (match(tosec, init_data_sections) &&
            match(fromsec, data_sections) &&
-           (strncmp(atsym, "__param", strlen("__param")) == 0))
-               return 1;
+           (strncmp(fromsym, "__param", strlen("__param")) == 0))
+               return 0;
 
        /* Check for pattern 2 */
        if (match(tosec, init_exit_sections) &&
            match(fromsec, data_sections) &&
-           match(atsym, symbol_white_list))
-               return 1;
+           match(fromsym, symbol_white_list))
+               return 0;
 
        /* Check for pattern 3 */
        if (match(fromsec, head_sections) &&
            match(tosec, init_sections))
-       return 1;
+               return 0;
 
        /* Check for pattern 4 */
-       if (match(refsymname, linker_symbols))
-               return 1;
+       if (match(tosym, linker_symbols))
+               return 0;
 
-       return 0;
+       return 1;
 }
 
 /**
@@ -987,41 +988,49 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
        return near;
 }
 
-/**
+/*
  * Print a warning about a section mismatch.
  * Try to find symbols near it so user can find it.
  * Check whitelist before warning - it may be a false positive.
- **/
-static void warn_sec_mismatch(const char *modname, const char *fromsec,
-                             struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
+ */
+static void report_sec_mismatch(const char *modname,
+                                const char *fromsec,
+                                unsigned long long fromaddr,
+                                const char *fromsym,
+                                const char *tosec, const char *tosym)
 {
-       Elf_Sym *where;
-       Elf_Sym *refsym;
-       const char *refsymname = "";
-       const char *secname;
-
-       secname = sec_name(elf, sym->st_shndx);
-       where = find_elf_symbol2(elf, r.r_offset, fromsec);
-
-       refsym = find_elf_symbol(elf, r.r_addend, sym);
-       if (refsym && strlen(sym_name(elf, refsym)))
-               refsymname = sym_name(elf, refsym);
-
-       /* check whitelist - we may ignore it */
-       if (secref_whitelist(modname, secname, fromsec,
-                            where ? sym_name(elf, where) : "",
-                            refsymname))
-               return;
-
-       if (where) {
+       if (strlen(tosym)) {
                warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s "
                     "in '%s'\n",
-                    modname, fromsec, (unsigned long long)r.r_offset,
-                    secname, refsymname, sym_name(elf, where));
+                    modname, fromsec, fromaddr,
+                    tosec, tosym, fromsym);
        } else {
                warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",
-                    modname, fromsec, (unsigned long long)r.r_offset,
-                    secname, refsymname);
+                    modname, fromsec, fromaddr,
+                    tosec, tosym);
+       }
+}
+
+static void check_section_mismatch(const char *modname, struct elf_info *elf,
+                                   Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
+{
+       const char *tosec;
+
+       tosec = sec_name(elf, sym->st_shndx);
+       if (section_mismatch(fromsec, tosec)) {
+               const char *fromsym;
+               const char *tosym;
+
+               fromsym = sym_name(elf,
+                         find_elf_symbol2(elf, r->r_offset, fromsec));
+               tosym = sym_name(elf,
+                       find_elf_symbol(elf, r->r_addend, sym));
+
+               /* check whitelist - we may ignore it */
+               if (secref_whitelist(fromsec, fromsym, tosec, tosym)) {
+                       report_sec_mismatch(modname, fromsec, r->r_offset,
+                                           fromsym, tosec, tosym);
+               }
        }
 }
 
@@ -1107,7 +1116,6 @@ static void section_rela(const char *modname, struct elf_info *elf,
        Elf_Rela r;
        unsigned int r_sym;
        const char *fromsec;
-       const char * tosec;
 
        Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;
        Elf_Rela *stop  = (void *)start + sechdr->sh_size;
@@ -1117,7 +1125,6 @@ static void section_rela(const char *modname, struct elf_info *elf,
        /* if from section (name) is know good then skip it */
        if (match(fromsec, section_white_list))
                return;
-
        for (rela = start; rela < stop; rela++) {
                r.r_offset = TO_NATIVE(rela->r_offset);
 #if KERNEL_ELFCLASS == ELFCLASS64
@@ -1140,10 +1147,7 @@ static void section_rela(const char *modname, struct elf_info *elf,
                /* Skip special sections */
                if (sym->st_shndx >= SHN_LORESERVE)
                        continue;
-
-               tosec = sec_name(elf, sym->st_shndx);
-               if (section_mismatch(fromsec, tosec))
-                       warn_sec_mismatch(modname, fromsec, elf, sym, r);
+               check_section_mismatch(modname, elf, &r, sym, fromsec);
        }
 }
 
@@ -1155,7 +1159,6 @@ static void section_rel(const char *modname, struct elf_info *elf,
        Elf_Rela r;
        unsigned int r_sym;
        const char *fromsec;
-       const char * tosec;
 
        Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;
        Elf_Rel *stop  = (void *)start + sechdr->sh_size;
@@ -1202,10 +1205,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
                /* Skip special sections */
                if (sym->st_shndx >= SHN_LORESERVE)
                        continue;
-
-               tosec = sec_name(elf, sym->st_shndx);
-               if (section_mismatch(fromsec, tosec))
-                       warn_sec_mismatch(modname, fromsec, elf, sym, r);
+               check_section_mismatch(modname, elf, &r, sym, fromsec);
        }
 }