summaryrefslogtreecommitdiff
path: root/scripts/mod/modpost.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mod/modpost.c')
-rw-r--r--scripts/mod/modpost.c137
1 files changed, 38 insertions, 99 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index f882ce0d9327..24725e50c7b4 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -17,7 +17,6 @@
#include <ctype.h>
#include <string.h>
#include <limits.h>
-#include <stdbool.h>
#include <errno.h>
#include "modpost.h"
#include "../../include/linux/license.h"
@@ -34,15 +33,18 @@ static int external_module = 0;
static int warn_unresolved = 0;
/* How a symbol is exported */
static int sec_mismatch_count = 0;
-static int sec_mismatch_fatal = 0;
+static int sec_mismatch_warn_only = true;
/* ignore missing files */
static int ignore_missing_files;
/* If set to 1, only warn (instead of error) about missing ns imports */
static int allow_missing_ns_imports;
+static bool error_occurred;
+
enum export {
- export_plain, export_unused, export_gpl,
- export_unused_gpl, export_gpl_future, export_unknown
+ export_plain,
+ export_gpl,
+ export_unknown
};
/* In kernel, this size is defined in linux/module.h;
@@ -78,14 +80,8 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
if (loglevel == LOG_FATAL)
exit(1);
-}
-
-static inline bool strends(const char *str, const char *postfix)
-{
- if (strlen(str) < strlen(postfix))
- return false;
-
- return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+ if (loglevel == LOG_ERROR)
+ error_occurred = true;
}
void *do_nofail(void *ptr, const char *expr)
@@ -297,10 +293,7 @@ static const struct {
enum export export;
} export_list[] = {
{ .str = "EXPORT_SYMBOL", .export = export_plain },
- { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused },
{ .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
- { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl },
- { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
{ .str = "(unknown)", .export = export_unknown },
};
@@ -359,14 +352,8 @@ static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
if (strstarts(secname, "___ksymtab+"))
return export_plain;
- else if (strstarts(secname, "___ksymtab_unused+"))
- return export_unused;
else if (strstarts(secname, "___ksymtab_gpl+"))
return export_gpl;
- else if (strstarts(secname, "___ksymtab_unused_gpl+"))
- return export_unused_gpl;
- else if (strstarts(secname, "___ksymtab_gpl_future+"))
- return export_gpl_future;
else
return export_unknown;
}
@@ -375,14 +362,8 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
{
if (sec == elf->export_sec)
return export_plain;
- else if (sec == elf->export_unused_sec)
- return export_unused;
else if (sec == elf->export_gpl_sec)
return export_gpl;
- else if (sec == elf->export_unused_gpl_sec)
- return export_unused_gpl;
- else if (sec == elf->export_gpl_future_sec)
- return export_gpl_future;
else
return export_unknown;
}
@@ -403,8 +384,8 @@ static void sym_update_namespace(const char *symname, const char *namespace)
* actually an assertion.
*/
if (!s) {
- merror("Could not update namespace(%s) for symbol %s\n",
- namespace, symname);
+ error("Could not update namespace(%s) for symbol %s\n",
+ namespace, symname);
return;
}
@@ -586,14 +567,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
info->modinfo_len = sechdrs[i].sh_size;
} else if (strcmp(secname, "__ksymtab") == 0)
info->export_sec = i;
- else if (strcmp(secname, "__ksymtab_unused") == 0)
- info->export_unused_sec = i;
else if (strcmp(secname, "__ksymtab_gpl") == 0)
info->export_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_unused_gpl") == 0)
- info->export_unused_gpl_sec = i;
- else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
- info->export_gpl_future_sec = i;
if (sechdrs[i].sh_type == SHT_SYMTAB) {
unsigned int sh_link_idx;
@@ -1984,6 +1959,10 @@ static char *remove_dot(char *s)
size_t m = strspn(s + n + 1, "0123456789");
if (m && (s[n + m] == '.' || s[n + m] == 0))
s[n] = 0;
+
+ /* strip trailing .lto */
+ if (strends(s, ".lto"))
+ s[strlen(s) - 4] = '\0';
}
return s;
}
@@ -2007,6 +1986,9 @@ static void read_symbols(const char *modname)
/* strip trailing .o */
tmp = NOFAIL(strdup(modname));
tmp[strlen(tmp) - 2] = '\0';
+ /* strip trailing .lto */
+ if (strends(tmp, ".lto"))
+ tmp[strlen(tmp) - 4] = '\0';
mod = new_module(tmp);
free(tmp);
}
@@ -2014,7 +1996,7 @@ static void read_symbols(const char *modname)
if (!mod->is_vmlinux) {
license = get_modinfo(&info, "license");
if (!license)
- warn("missing MODULE_LICENSE() in %s\n", modname);
+ error("missing MODULE_LICENSE() in %s\n", modname);
while (license) {
if (license_is_gpl_compatible(license))
mod->gpl_compatible = 1;
@@ -2141,55 +2123,28 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
{
switch (exp) {
case export_gpl:
- fatal("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
- m, s);
- break;
- case export_unused_gpl:
- fatal("GPL-incompatible module %s.ko uses GPL-only symbol marked UNUSED '%s'\n",
+ error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
m, s);
break;
- case export_gpl_future:
- warn("GPL-incompatible module %s.ko uses future GPL-only symbol '%s'\n",
- m, s);
- break;
case export_plain:
- case export_unused:
case export_unknown:
/* ignore */
break;
}
}
-static void check_for_unused(enum export exp, const char *m, const char *s)
-{
- switch (exp) {
- case export_unused:
- case export_unused_gpl:
- warn("module %s.ko uses symbol '%s' marked UNUSED\n",
- m, s);
- break;
- default:
- /* ignore */
- break;
- }
-}
-
-static int check_exports(struct module *mod)
+static void 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 (have_vmlinux && !s->weak) {
+ if (have_vmlinux && !s->weak)
modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR,
"\"%s\" [%s.ko] undefined!\n",
s->name, mod->name);
- if (!warn_unresolved)
- err = 1;
- }
continue;
}
basename = strrchr(mod->name, '/');
@@ -2203,20 +2158,15 @@ static int check_exports(struct module *mod)
modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,
"module %s uses symbol %s from namespace %s, but does not import it.\n",
basename, exp->name, exp->namespace);
- if (!allow_missing_ns_imports)
- err = 1;
add_namespace(&mod->missing_namespaces, exp->namespace);
}
if (!mod->gpl_compatible)
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)
+static void check_modname_len(struct module *mod)
{
const char *mod_name;
@@ -2225,12 +2175,8 @@ static int check_modname_len(struct module *mod)
mod_name = mod->name;
else
mod_name++;
- if (strlen(mod_name) >= MODULE_NAME_LEN) {
- merror("module name is too long [%s.ko]\n", mod->name);
- return 1;
- }
-
- return 0;
+ if (strlen(mod_name) >= MODULE_NAME_LEN)
+ error("module name is too long [%s.ko]\n", mod->name);
}
/**
@@ -2289,10 +2235,9 @@ static void add_staging_flag(struct buffer *b, const char *name)
/**
* Record CRCs for unresolved symbols
**/
-static int add_versions(struct buffer *b, struct module *mod)
+static void add_versions(struct buffer *b, struct module *mod)
{
struct symbol *s, *exp;
- int err = 0;
for (s = mod->unres; s; s = s->next) {
exp = find_symbol(s->name);
@@ -2304,7 +2249,7 @@ static int add_versions(struct buffer *b, struct module *mod)
}
if (!modversions)
- return err;
+ return;
buf_printf(b, "\n");
buf_printf(b, "static const struct modversion_info ____versions[]\n");
@@ -2319,9 +2264,8 @@ static int add_versions(struct buffer *b, struct module *mod)
continue;
}
if (strlen(s->name) >= MODULE_NAME_LEN) {
- merror("too long symbol \"%s\" [%s.ko]\n",
- s->name, mod->name);
- err = 1;
+ error("too long symbol \"%s\" [%s.ko]\n",
+ s->name, mod->name);
break;
}
buf_printf(b, "\t{ %#8x, \"%s\" },\n",
@@ -2329,8 +2273,6 @@ static int add_versions(struct buffer *b, struct module *mod)
}
buf_printf(b, "};\n");
-
- return err;
}
static void add_depends(struct buffer *b, struct module *mod)
@@ -2554,7 +2496,6 @@ int main(int argc, char **argv)
char *missing_namespace_deps = NULL;
char *dump_write = NULL, *files_source = NULL;
int opt;
- int err;
int n;
struct dump_list *dump_read_start = NULL;
struct dump_list **dump_read_iter = &dump_read_start;
@@ -2589,7 +2530,7 @@ int main(int argc, char **argv)
warn_unresolved = 1;
break;
case 'E':
- sec_mismatch_fatal = 1;
+ sec_mismatch_warn_only = false;
break;
case 'N':
allow_missing_ns_imports = 1;
@@ -2624,8 +2565,6 @@ int main(int argc, char **argv)
if (!have_vmlinux)
warn("Symbol info of vmlinux is missing. Unresolved symbol check will be entirely skipped.\n");
- err = 0;
-
for (mod = modules; mod; mod = mod->next) {
char fname[PATH_MAX];
@@ -2634,14 +2573,14 @@ int main(int argc, char **argv)
buf.pos = 0;
- err |= check_modname_len(mod);
- err |= check_exports(mod);
+ check_modname_len(mod);
+ 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_versions(&buf, mod);
add_depends(&buf, mod);
add_moddevtable(&buf, mod);
add_srcversion(&buf, mod);
@@ -2655,21 +2594,21 @@ int main(int argc, char **argv)
if (dump_write)
write_dump(dump_write);
- if (sec_mismatch_count && sec_mismatch_fatal)
- fatal("Section mismatches detected.\n"
+ if (sec_mismatch_count && !sec_mismatch_warn_only)
+ error("Section mismatches detected.\n"
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
struct symbol *s;
for (s = symbolhash[n]; s; s = s->next) {
if (s->is_static)
- warn("\"%s\" [%s] is a static %s\n",
- s->name, s->module->name,
- export_str(s->export));
+ error("\"%s\" [%s] is a static %s\n",
+ s->name, s->module->name,
+ export_str(s->export));
}
}
free(buf.p);
- return err;
+ return error_occurred ? 1 : 0;
}