modpost: change the license of EXPORT_SYMBOL to bool type
There were more EXPORT_SYMBOL types in the past. The following commits removed unused ones. -f1c3d73e97
("module: remove EXPORT_SYMBOL_GPL_FUTURE") -367948220f
("module: remove EXPORT_UNUSED_SYMBOL*") There are 3 remaining in enum export, but export_unknown does not make any sense because we never expect such a situation like "we do not know how it was exported". If the symbol name starts with "__ksymtab_", but the section name does not start with "___ksymtab+" or "___ksymtab_gpl+", it is not an exported symbol. It occurs when a variable starting with "__ksymtab_" is directly defined: int __ksymtab_foo; Presumably, there is no practical issue for using such a weird variable name (but there is no good reason for doing so, either). Anyway, that is not an exported symbol. Setting export_unknown is not the right thing to do. Do not call sym_add_exported() in this case. With pointless export_unknown removed, the export type finally becomes boolean (either EXPORT_SYMBOL or EXPORT_SYMBOL_GPL). I renamed the field name to is_gpl_only. EXPORT_SYMBOL_GPL sets it true. Only GPL-compatible modules can use it. I removed the orphan comment, "How a symbol is exported", which is unrelated to sec_mismatch_count. It is about enum export. See commitbd5cbcedf4
("kbuild: export-type enhancement to modpost.c") Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> Reviewed-by: Nicolas Schier <nicolas@fjasle.eu> Tested-by: Nathan Chancellor <nathan@kernel.org>
This commit is contained in:
@ -30,7 +30,7 @@ static bool all_versions;
|
|||||||
static bool external_module;
|
static bool external_module;
|
||||||
/* Only warn about unresolved symbols */
|
/* Only warn about unresolved symbols */
|
||||||
static bool warn_unresolved;
|
static bool warn_unresolved;
|
||||||
/* How a symbol is exported */
|
|
||||||
static int sec_mismatch_count;
|
static int sec_mismatch_count;
|
||||||
static bool sec_mismatch_warn_only = true;
|
static bool sec_mismatch_warn_only = true;
|
||||||
/* ignore missing files */
|
/* ignore missing files */
|
||||||
@ -47,12 +47,6 @@ static bool error_occurred;
|
|||||||
#define MAX_UNRESOLVED_REPORTS 10
|
#define MAX_UNRESOLVED_REPORTS 10
|
||||||
static unsigned int nr_unresolved;
|
static unsigned int nr_unresolved;
|
||||||
|
|
||||||
enum export {
|
|
||||||
export_plain,
|
|
||||||
export_gpl,
|
|
||||||
export_unknown
|
|
||||||
};
|
|
||||||
|
|
||||||
/* In kernel, this size is defined in linux/module.h;
|
/* In kernel, this size is defined in linux/module.h;
|
||||||
* here we use Elf_Addr instead of long for covering cross-compile
|
* here we use Elf_Addr instead of long for covering cross-compile
|
||||||
*/
|
*/
|
||||||
@ -219,7 +213,7 @@ struct symbol {
|
|||||||
bool crc_valid;
|
bool crc_valid;
|
||||||
bool weak;
|
bool weak;
|
||||||
bool is_static; /* true if symbol is not global */
|
bool is_static; /* true if symbol is not global */
|
||||||
enum export export; /* Type of export */
|
bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */
|
||||||
char name[];
|
char name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -316,34 +310,6 @@ static void add_namespace(struct list_head *head, const char *namespace)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct {
|
|
||||||
const char *str;
|
|
||||||
enum export export;
|
|
||||||
} export_list[] = {
|
|
||||||
{ .str = "EXPORT_SYMBOL", .export = export_plain },
|
|
||||||
{ .str = "EXPORT_SYMBOL_GPL", .export = export_gpl },
|
|
||||||
{ .str = "(unknown)", .export = export_unknown },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static const char *export_str(enum export ex)
|
|
||||||
{
|
|
||||||
return export_list[ex].str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum export export_no(const char *s)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!s)
|
|
||||||
return export_unknown;
|
|
||||||
for (i = 0; export_list[i].export != export_unknown; i++) {
|
|
||||||
if (strcmp(export_list[i].str, s) == 0)
|
|
||||||
return export_list[i].export;
|
|
||||||
}
|
|
||||||
return export_unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *sym_get_data_by_offset(const struct elf_info *info,
|
static void *sym_get_data_by_offset(const struct elf_info *info,
|
||||||
unsigned int secindex, unsigned long offset)
|
unsigned int secindex, unsigned long offset)
|
||||||
{
|
{
|
||||||
@ -374,18 +340,6 @@ static const char *sec_name(const struct elf_info *info, int secindex)
|
|||||||
|
|
||||||
#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
|
#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
|
||||||
|
|
||||||
static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
|
|
||||||
{
|
|
||||||
const char *secname = sec_name(elf, sec);
|
|
||||||
|
|
||||||
if (strstarts(secname, "___ksymtab+"))
|
|
||||||
return export_plain;
|
|
||||||
else if (strstarts(secname, "___ksymtab_gpl+"))
|
|
||||||
return export_gpl;
|
|
||||||
else
|
|
||||||
return export_unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sym_update_namespace(const char *symname, const char *namespace)
|
static void sym_update_namespace(const char *symname, const char *namespace)
|
||||||
{
|
{
|
||||||
struct symbol *s = find_symbol(symname);
|
struct symbol *s = find_symbol(symname);
|
||||||
@ -405,7 +359,7 @@ static void sym_update_namespace(const char *symname, const char *namespace)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct symbol *sym_add_exported(const char *name, struct module *mod,
|
static struct symbol *sym_add_exported(const char *name, struct module *mod,
|
||||||
enum export export)
|
bool gpl_only)
|
||||||
{
|
{
|
||||||
struct symbol *s = find_symbol(name);
|
struct symbol *s = find_symbol(name);
|
||||||
|
|
||||||
@ -417,7 +371,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
|
|||||||
|
|
||||||
s = alloc_symbol(name);
|
s = alloc_symbol(name);
|
||||||
s->module = mod;
|
s->module = mod;
|
||||||
s->export = export;
|
s->is_gpl_only = gpl_only;
|
||||||
list_add_tail(&s->list, &mod->exported_symbols);
|
list_add_tail(&s->list, &mod->exported_symbols);
|
||||||
hash_add_symbol(s);
|
hash_add_symbol(s);
|
||||||
|
|
||||||
@ -689,8 +643,6 @@ static void handle_modversion(const struct module *mod,
|
|||||||
static void handle_symbol(struct module *mod, struct elf_info *info,
|
static void handle_symbol(struct module *mod, struct elf_info *info,
|
||||||
const Elf_Sym *sym, const char *symname)
|
const Elf_Sym *sym, const char *symname)
|
||||||
{
|
{
|
||||||
const char *name;
|
|
||||||
|
|
||||||
switch (sym->st_shndx) {
|
switch (sym->st_shndx) {
|
||||||
case SHN_COMMON:
|
case SHN_COMMON:
|
||||||
if (strstarts(symname, "__gnu_lto_")) {
|
if (strstarts(symname, "__gnu_lto_")) {
|
||||||
@ -724,12 +676,15 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
|
|||||||
default:
|
default:
|
||||||
/* All exported symbols */
|
/* All exported symbols */
|
||||||
if (strstarts(symname, "__ksymtab_")) {
|
if (strstarts(symname, "__ksymtab_")) {
|
||||||
enum export export;
|
const char *name, *secname;
|
||||||
|
|
||||||
name = symname + strlen("__ksymtab_");
|
name = symname + strlen("__ksymtab_");
|
||||||
export = export_from_secname(info,
|
secname = sec_name(info, get_secindex(info, sym));
|
||||||
get_secindex(info, sym));
|
|
||||||
sym_add_exported(name, mod, export);
|
if (strstarts(secname, "___ksymtab_gpl+"))
|
||||||
|
sym_add_exported(name, mod, true);
|
||||||
|
else if (strstarts(secname, "___ksymtab+"))
|
||||||
|
sym_add_exported(name, mod, false);
|
||||||
}
|
}
|
||||||
if (strcmp(symname, "init_module") == 0)
|
if (strcmp(symname, "init_module") == 0)
|
||||||
mod->has_init = true;
|
mod->has_init = true;
|
||||||
@ -2140,20 +2095,6 @@ void buf_write(struct buffer *buf, const char *s, int len)
|
|||||||
buf->pos += len;
|
buf->pos += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_for_gpl_usage(enum export exp, const char *m, const char *s)
|
|
||||||
{
|
|
||||||
switch (exp) {
|
|
||||||
case export_gpl:
|
|
||||||
error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
|
|
||||||
m, s);
|
|
||||||
break;
|
|
||||||
case export_plain:
|
|
||||||
case export_unknown:
|
|
||||||
/* ignore */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_exports(struct module *mod)
|
static void check_exports(struct module *mod)
|
||||||
{
|
{
|
||||||
struct symbol *s, *exp;
|
struct symbol *s, *exp;
|
||||||
@ -2192,8 +2133,9 @@ static void check_exports(struct module *mod)
|
|||||||
add_namespace(&mod->missing_namespaces, exp->namespace);
|
add_namespace(&mod->missing_namespaces, exp->namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mod->is_gpl_compatible)
|
if (!mod->is_gpl_compatible && exp->is_gpl_only)
|
||||||
check_for_gpl_usage(exp->export, basename, exp->name);
|
error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
|
||||||
|
basename, exp->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2437,6 +2379,7 @@ static void read_dump(const char *fname)
|
|||||||
unsigned int crc;
|
unsigned int crc;
|
||||||
struct module *mod;
|
struct module *mod;
|
||||||
struct symbol *s;
|
struct symbol *s;
|
||||||
|
bool gpl_only;
|
||||||
|
|
||||||
if (!(symname = strchr(line, '\t')))
|
if (!(symname = strchr(line, '\t')))
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -2454,12 +2397,22 @@ static void read_dump(const char *fname)
|
|||||||
crc = strtoul(line, &d, 16);
|
crc = strtoul(line, &d, 16);
|
||||||
if (*symname == '\0' || *modname == '\0' || *d != '\0')
|
if (*symname == '\0' || *modname == '\0' || *d != '\0')
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if (!strcmp(export, "EXPORT_SYMBOL_GPL")) {
|
||||||
|
gpl_only = true;
|
||||||
|
} else if (!strcmp(export, "EXPORT_SYMBOL")) {
|
||||||
|
gpl_only = false;
|
||||||
|
} else {
|
||||||
|
error("%s: unknown license %s. skip", symname, export);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
mod = find_module(modname);
|
mod = find_module(modname);
|
||||||
if (!mod) {
|
if (!mod) {
|
||||||
mod = new_module(modname);
|
mod = new_module(modname);
|
||||||
mod->from_dump = true;
|
mod->from_dump = true;
|
||||||
}
|
}
|
||||||
s = sym_add_exported(symname, mod, export_no(export));
|
s = sym_add_exported(symname, mod, gpl_only);
|
||||||
s->is_static = false;
|
s->is_static = false;
|
||||||
sym_set_crc(symname, crc);
|
sym_set_crc(symname, crc);
|
||||||
sym_update_namespace(symname, namespace);
|
sym_update_namespace(symname, namespace);
|
||||||
@ -2481,9 +2434,9 @@ static void write_dump(const char *fname)
|
|||||||
if (mod->from_dump)
|
if (mod->from_dump)
|
||||||
continue;
|
continue;
|
||||||
list_for_each_entry(sym, &mod->exported_symbols, list) {
|
list_for_each_entry(sym, &mod->exported_symbols, list) {
|
||||||
buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n",
|
buf_printf(&buf, "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n",
|
||||||
sym->crc, sym->name, mod->name,
|
sym->crc, sym->name, mod->name,
|
||||||
export_str(sym->export),
|
sym->is_gpl_only ? "_GPL" : "",
|
||||||
sym->namespace ?: "");
|
sym->namespace ?: "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2604,9 +2557,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
for (s = symbolhash[n]; s; s = s->next) {
|
for (s = symbolhash[n]; s; s = s->next) {
|
||||||
if (s->is_static)
|
if (s->is_static)
|
||||||
error("\"%s\" [%s] is a static %s\n",
|
error("\"%s\" [%s] is a static EXPORT_SYMBOL\n",
|
||||||
s->name, s->module->name,
|
s->name, s->module->name);
|
||||||
export_str(s->export));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user