aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/mod/modpost.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r--scripts/mod/modpost.c114
1 files changed, 63 insertions, 51 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0d998c54564d..0de2fb236640 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1163,6 +1163,14 @@ static const struct sectioncheck *section_mismatch(
* fromsec = text section
* refsymname = *.constprop.*
*
+ * Pattern 6:
+ * Hide section mismatch warnings for ELF local symbols. The goal
+ * is to eliminate false positive modpost warnings caused by
+ * compiler-generated ELF local symbol names such as ".LANCHOR1".
+ * Autogenerated symbol names bypass modpost's "Pattern 2"
+ * whitelisting, which relies on pattern-matching against symbol
+ * names to work. (One situation where gcc can autogenerate ELF
+ * local symbols is when "-fsection-anchors" is used.)
**/
static int secref_whitelist(const struct sectioncheck *mismatch,
const char *fromsec, const char *fromsym,
@@ -1201,9 +1209,37 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
match(fromsym, optim_symbols))
return 0;
+ /* Check for pattern 6 */
+ if (strstarts(fromsym, ".L"))
+ return 0;
+
return 1;
}
+static inline int is_arm_mapping_symbol(const char *str)
+{
+ return str[0] == '$' && strchr("axtd", str[1])
+ && (str[2] == '\0' || str[2] == '.');
+}
+
+/*
+ * If there's no name there, ignore it; likewise, ignore it if it's
+ * one of the magic symbols emitted used by current ARM tools.
+ *
+ * Otherwise if find_symbols_between() returns those symbols, they'll
+ * fail the whitelist tests and cause lots of false alarms ... fixable
+ * only by merging __exit and __init sections into __text, bloating
+ * the kernel (which is especially evil on embedded platforms).
+ */
+static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
+{
+ const char *name = elf->strtab + sym->st_name;
+
+ if (!name || !strlen(name))
+ return 0;
+ return !is_arm_mapping_symbol(name);
+}
+
/**
* Find symbol based on relocation record info.
* In some cases the symbol supplied is a valid symbol so
@@ -1229,6 +1265,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
continue;
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
continue;
+ if (!is_valid_name(elf, sym))
+ continue;
if (sym->st_value == addr)
return sym;
/* Find a symbol nearby - addr are maybe negative */
@@ -1247,30 +1285,6 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr,
return NULL;
}
-static inline int is_arm_mapping_symbol(const char *str)
-{
- return str[0] == '$' && strchr("axtd", str[1])
- && (str[2] == '\0' || str[2] == '.');
-}
-
-/*
- * If there's no name there, ignore it; likewise, ignore it if it's
- * one of the magic symbols emitted used by current ARM tools.
- *
- * Otherwise if find_symbols_between() returns those symbols, they'll
- * fail the whitelist tests and cause lots of false alarms ... fixable
- * only by merging __exit and __init sections into __text, bloating
- * the kernel (which is especially evil on embedded platforms).
- */
-static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
-{
- const char *name = elf->strtab + sym->st_name;
-
- if (!name || !strlen(name))
- return 0;
- return !is_arm_mapping_symbol(name);
-}
-
/*
* 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.
@@ -2083,15 +2097,27 @@ static void check_for_unused(enum export exp, const char *m, const char *s)
}
}
-static void check_exports(struct module *mod)
+static int check_exports(struct module *mod)
{
struct symbol *s, *exp;
+ int err = 0;
for (s = mod->unres; s; s = s->next) {
const char *basename;
exp = find_symbol(s->name);
- if (!exp || exp->module == mod)
+ if (!exp || exp->module == mod) {
+ if (have_vmlinux && !s->weak) {
+ if (warn_unresolved) {
+ warn("\"%s\" [%s.ko] undefined!\n",
+ s->name, mod->name);
+ } else {
+ merror("\"%s\" [%s.ko] undefined!\n",
+ s->name, mod->name);
+ err = 1;
+ }
+ }
continue;
+ }
basename = strrchr(mod->name, '/');
if (basename)
basename++;
@@ -2101,6 +2127,8 @@ static void check_exports(struct module *mod)
check_for_gpl_usage(exp->export, basename, exp->name);
check_for_unused(exp->export, basename, exp->name);
}
+
+ return err;
}
static int check_modname_len(struct module *mod)
@@ -2178,19 +2206,8 @@ static int add_versions(struct buffer *b, struct module *mod)
for (s = mod->unres; s; s = s->next) {
exp = find_symbol(s->name);
- if (!exp || exp->module == mod) {
- if (have_vmlinux && !s->weak) {
- if (warn_unresolved) {
- warn("\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
- } else {
- merror("\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
- err = 1;
- }
- }
+ if (!exp || exp->module == mod)
continue;
- }
s->module = exp->module;
s->crc_valid = exp->crc_valid;
s->crc = exp->crc;
@@ -2227,15 +2244,15 @@ static int add_versions(struct buffer *b, struct module *mod)
return err;
}
-static void add_depends(struct buffer *b, struct module *mod,
- struct module *modules)
+static void add_depends(struct buffer *b, struct module *mod)
{
struct symbol *s;
- struct module *m;
int first = 1;
- for (m = modules; m; m = m->next)
- m->seen = is_vmlinux(m->name);
+ /* Clear ->seen flag of modules that own symbols needed by this. */
+ for (s = mod->unres; s; s = s->next)
+ if (s->module)
+ s->module->seen = is_vmlinux(s->module->name);
buf_printf(b, "\n");
buf_printf(b, "static const char __module_depends[]\n");
@@ -2416,7 +2433,7 @@ int main(int argc, char **argv)
struct ext_sym_list *extsym_iter;
struct ext_sym_list *extsym_start = NULL;
- while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awM:K:E")) != -1) {
+ while ((opt = getopt(argc, argv, "i:I:e:mnsST:o:awE")) != -1) {
switch (opt) {
case 'i':
kernel_read = optarg;
@@ -2482,12 +2499,6 @@ int main(int argc, char **argv)
if (files_source)
read_symbols_from_files(files_source);
- for (mod = modules; mod; mod = mod->next) {
- if (mod->skip)
- continue;
- check_exports(mod);
- }
-
err = 0;
for (mod = modules; mod; mod = mod->next) {
@@ -2499,12 +2510,13 @@ int main(int argc, char **argv)
buf.pos = 0;
err |= check_modname_len(mod);
+ err |= check_exports(mod);
add_header(&buf, mod);
add_intree_flag(&buf, !external_module);
add_retpoline(&buf);
add_staging_flag(&buf, mod->name);
err |= add_versions(&buf, mod);
- add_depends(&buf, mod, modules);
+ add_depends(&buf, mod);
add_moddevtable(&buf, mod);
add_srcversion(&buf, mod);