kbuild: simplified warning report in modpost

Refactor code so the warning report function
does nothing else than reporting warnings.
As a side effect some other code paths were cleaned
up by this.

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
Sam Ravnborg 2008-01-23 21:13:50 +01:00
parent ff13f92690
commit 58fb0d4f2f

View 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);
}
}