aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/mod/modpost.c104
1 files changed, 52 insertions, 52 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index e4099cd5f08..0a80acafd21 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -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);
}
}