]> Pileus Git - ~andy/linux/blobdiff - scripts/mod/modpost.c
Merge branch 'master'
[~andy/linux] / scripts / mod / modpost.c
index 5de3c63091e9fb9a001de0b50789fde7a4c01d42..cd00e9f0758995e5d027ff9dc96835256b10860c 100644 (file)
@@ -191,7 +191,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod)
                s = new_symbol(name, mod);
        } else {
                if (!s->preloaded) {
-                       warn("%s: duplicate symbol '%s' previous definition "
+                       warn("%s: '%s' exported twice. Previous export "
                             "was in %s%s\n", mod->name, name,
                             s->module->name,
                             is_vmlinux(s->module->name) ?"":".ko");
@@ -346,8 +346,8 @@ static void parse_elf_finish(struct elf_info *info)
        release_file(info->hdr, info->size);
 }
 
-#define CRC_PFX     "__crc_"
-#define KSYMTAB_PFX "__ksymtab_"
+#define CRC_PFX     MODULE_SYMBOL_PREFIX "__crc_"
+#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
 
 static void handle_modversions(struct module *mod, struct elf_info *info,
                               Elf_Sym *sym, const char *symname)
@@ -483,7 +483,7 @@ static int strrcmp(const char *s, const char *sub)
  *   this pattern.
  *   The pattern is identified by:
  *   tosec   = .init.data
- *   fromsec = .data
+ *   fromsec = .data*
  *   atsym   =__param*
  *
  * Pattern 2:
@@ -492,17 +492,19 @@ 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
+ *   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",
+               "_template", /* scsi uses *_template a lot */
+               "_sht",      /* scsi also used *_sht to some extent */
                "_ops",
                "_probe",
                "_probe_one",
@@ -512,7 +514,7 @@ static int secref_whitelist(const char *tosec, const char *fromsec,
        /* Check for pattern 1 */
        if (strcmp(tosec, ".init.data") != 0)
                f1 = 0;
-       if (strcmp(fromsec, ".data") != 0)
+       if (strncmp(fromsec, ".data", strlen(".data")) != 0)
                f1 = 0;
        if (strncmp(atsym, "__param", strlen("__param")) != 0)
                f1 = 0;
@@ -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;
@@ -558,7 +561,10 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
 }
 
 /*
- * Find symbols before or equal addr and after addr - in the section sec
+ * Find symbols before or equal addr and after addr - in the section sec.
+ * If we find two symbols with equal offset prefer one with a valid name.
+ * The ELF format may have a better way to detect what type of symbol
+ * it is, but this works for now.
  **/
 static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
                                 const char *sec,
@@ -587,6 +593,12 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
                                beforediff = addr - sym->st_value;
                                *before = sym;
                        }
+                       else if ((addr - sym->st_value) == beforediff) {
+                               /* equal offset, valid name? */
+                               const char *name = elf->strtab + sym->st_name;
+                               if (name && strlen(name))
+                                       *before = sym;
+                       }
                }
                else
                {
@@ -594,6 +606,12 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
                                afterdiff = sym->st_value - addr;
                                *after = sym;
                        }
+                       else if ((sym->st_value - addr) == afterdiff) {
+                               /* equal offset, valid name? */
+                               const char *name = elf->strtab + sym->st_name;
+                               if (name && strlen(name))
+                                       *after = sym;
+                       }
                }
        }
 }
@@ -643,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 "
@@ -743,9 +761,12 @@ static int init_section_ref_ok(const char *name)
        /* Absolute section names */
        const char *namelist1[] = {
                ".init",
+               ".opd",   /* see comment [OPD] at exit_section_ref_ok() */
+               ".toc1",  /* used by ppc64 */
                ".stab",
                ".rodata",
                ".text.lock",
+               "__bug_table", /* used by powerpc for BUG() */
                ".pci_fixup_header",
                ".pci_fixup_final",
                ".pdr",
@@ -773,7 +794,7 @@ static int init_section_ref_ok(const char *name)
                if (strncmp(*s, name, strlen(*s)) == 0)
                        return 1;
        for (s = namelist3; *s; s++)
-               if (strstr(*s, name) != NULL)
+               if (strstr(name, *s) != NULL)
                        return 1;
        return 0;
 }
@@ -802,6 +823,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)
 {
@@ -811,9 +833,12 @@ 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",
                ".pdr",
+               "__bug_table", /* used by powerpc for BUG() */
                ".exitcall.exit",
                ".eh_frame",
                ".stab",
@@ -837,7 +862,7 @@ static int exit_section_ref_ok(const char *name)
                if (strncmp(*s, name, strlen(*s)) == 0)
                        return 1;
        for (s = namelist3; *s; s++)
-               if (strstr(*s, name) != NULL)
+               if (strstr(name, *s) != NULL)
                        return 1;
        return 0;
 }
@@ -903,19 +928,14 @@ void __attribute__((format(printf, 2, 3))) buf_printf(struct buffer *buf,
 
        va_start(ap, fmt);
        len = vsnprintf(tmp, SZ, fmt, ap);
-       if (buf->size - buf->pos < len + 1) {
-               buf->size += 128;
-               buf->p = realloc(buf->p, buf->size);
-       }
-       strncpy(buf->p + buf->pos, tmp, len + 1);
-       buf->pos += len;
+       buf_write(buf, tmp, len);
        va_end(ap);
 }
 
 void buf_write(struct buffer *buf, const char *s, int len)
 {
        if (buf->size - buf->pos < len) {
-               buf->size += len;
+               buf->size += len + SZ;
                buf->p = realloc(buf->p, buf->size);
        }
        strncpy(buf->p + buf->pos, s, len);