Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd5cbced authored by Ram Pai's avatar Ram Pai Committed by Sam Ravnborg
Browse files

kbuild: export-type enhancement to modpost.c



This patch provides the ability to identify the export-type of each
exported symbols in Module.symvers.

NOTE: It updates the Module.symvers file with the additional
information as shown below.

0x0f8b92af      platform_device_add_resources   vmlinux EXPORT_SYMBOL_GPL
0xcf7efb2a      ethtool_op_set_tx_csum          vmlinux EXPORT_SYMBOL

Signed-off-by: default avatarAndreas Gruenbacher <agruen@suse.de>
Signed-off-by: default avatarRam Pai <linuxram@us.ibm.com>
Signed-off-by: default avatarAvantika Mathur <mathur@us.ibm.com>
Signed-off-by: default avatarValdis Kletnieks <valdis.kletnieks@vt.edu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarSam Ravnborg <sam@ravnborg.org>
parent 031ecc6d
Loading
Loading
Loading
Loading
+77 −16
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ int have_vmlinux = 0;
static int all_versions = 0;
/* If we are modposting external module set to 1 */
static int external_module = 0;
/* How a symbol is exported */
enum export {export_plain, export_gpl, export_gpl_future, export_unknown};

void fatal(const char *fmt, ...)
{
@@ -118,6 +120,7 @@ struct symbol {
	unsigned int kernel:1;     /* 1 if symbol is from kernel
				    *  (only for external modules) **/
	unsigned int preloaded:1;  /* 1 if symbol from Module.symvers */
	enum export  export;       /* Type of export */
	char name[0];
};

@@ -153,7 +156,8 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak,
}

/* For the hash of exported symbols */
static struct symbol *new_symbol(const char *name, struct module *module)
static struct symbol *new_symbol(const char *name, struct module *module,
				 enum export export)
{
	unsigned int hash;
	struct symbol *new;
@@ -161,6 +165,7 @@ static struct symbol *new_symbol(const char *name, struct module *module)
	hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
	new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
	new->module = module;
	new->export = export;
	return new;
}

@@ -179,16 +184,55 @@ static struct symbol *find_symbol(const char *name)
	return NULL;
}

static struct {
	const char *str;
	enum export export;
} export_list[] = {
	{ .str = "EXPORT_SYMBOL",            .export = export_plain },
	{ .str = "EXPORT_SYMBOL_GPL",        .export = export_gpl },
	{ .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
	{ .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;
	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 enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
{
	if (sec == elf->export_sec)
		return export_plain;
	else if (sec == elf->export_gpl_sec)
		return export_gpl;
	else if (sec == elf->export_gpl_future_sec)
		return export_gpl_future;
	else
		return export_unknown;
}

/**
 * Add an exported symbol - it may have already been added without a
 * CRC, in this case just update the CRC
 **/
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)
{
	struct symbol *s = find_symbol(name);

	if (!s) {
		s = new_symbol(name, mod);
		s = new_symbol(name, mod, export);
	} else {
		if (!s->preloaded) {
			warn("%s: '%s' exported twice. Previous export "
@@ -200,16 +244,17 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod)
	s->preloaded = 0;
	s->vmlinux   = is_vmlinux(mod->name);
	s->kernel    = 0;
	s->export    = export;
	return s;
}

static void sym_update_crc(const char *name, struct module *mod,
			   unsigned int crc)
			   unsigned int crc, enum export export)
{
	struct symbol *s = find_symbol(name);

	if (!s)
		s = new_symbol(name, mod);
		s = new_symbol(name, mod, export);
	s->crc = crc;
	s->crc_valid = 1;
}
@@ -309,13 +354,21 @@ static void parse_elf(struct elf_info *info, const char *filename)
	for (i = 1; i < hdr->e_shnum; i++) {
		const char *secstrings
			= (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
		const char *secname;

		if (sechdrs[i].sh_offset > info->size)
			goto truncated;
		if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
		secname = secstrings + sechdrs[i].sh_name;
		if (strcmp(secname, ".modinfo") == 0) {
			info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
			info->modinfo_len = sechdrs[i].sh_size;
		}
		} else if (strcmp(secname, "__ksymtab") == 0)
			info->export_sec = i;
		else if (strcmp(secname, "__ksymtab_gpl") == 0)
			info->export_gpl_sec = i;
		else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
			info->export_gpl_future_sec = i;

		if (sechdrs[i].sh_type != SHT_SYMTAB)
			continue;

@@ -353,6 +406,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
			       Elf_Sym *sym, const char *symname)
{
	unsigned int crc;
	enum export export = export_from_sec(info, sym->st_shndx);

	switch (sym->st_shndx) {
	case SHN_COMMON:
@@ -362,7 +416,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
		/* CRC'd symbol */
		if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
			crc = (unsigned int) sym->st_value;
			sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
			sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
					export);
		}
		break;
	case SHN_UNDEF:
@@ -406,7 +461,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
	default:
		/* All exported symbols */
		if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
			sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
			sym_add_exported(symname + strlen(KSYMTAB_PFX), mod,
					export);
		}
		if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
			mod->has_init = 1;
@@ -1146,6 +1202,9 @@ static void write_if_changed(struct buffer *b, const char *fname)
	fclose(file);
}

/* parse Module.symvers file. line format:
 * 0x12345678<tab>symbol<tab>module[<tab>export]
 **/
static void read_dump(const char *fname, unsigned int kernel)
{
	unsigned long size, pos = 0;
@@ -1157,7 +1216,7 @@ static void read_dump(const char *fname, unsigned int kernel)
		return;

	while ((line = get_next_line(&pos, file, size))) {
		char *symname, *modname, *d;
		char *symname, *modname, *d, *export;
		unsigned int crc;
		struct module *mod;
		struct symbol *s;
@@ -1168,8 +1227,9 @@ static void read_dump(const char *fname, unsigned int kernel)
		if (!(modname = strchr(symname, '\t')))
			goto fail;
		*modname++ = '\0';
		if (strchr(modname, '\t'))
			goto fail;
		if (!(export = strchr(modname, '\t')))
			*export++ = '\0';

		crc = strtoul(line, &d, 16);
		if (*symname == '\0' || *modname == '\0' || *d != '\0')
			goto fail;
@@ -1181,10 +1241,10 @@ static void read_dump(const char *fname, unsigned int kernel)
			mod = new_module(NOFAIL(strdup(modname)));
			mod->skip = 1;
		}
		s = sym_add_exported(symname, mod);
		s = sym_add_exported(symname, mod, export_no(export));
		s->kernel    = kernel;
		s->preloaded = 1;
		sym_update_crc(symname, mod, crc);
		sym_update_crc(symname, mod, crc, export_no(export));
	}
	return;
fail:
@@ -1214,9 +1274,10 @@ static void write_dump(const char *fname)
		symbol = symbolhash[n];
		while (symbol) {
			if (dump_sym(symbol))
				buf_printf(&buf, "0x%08x\t%s\t%s\n",
				buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n",
					symbol->crc, symbol->name,
					symbol->module->name);
					symbol->module->name,
					export_str(symbol->export));
			symbol = symbol->next;
		}
	}
+3 −0
Original line number Diff line number Diff line
@@ -115,6 +115,9 @@ struct elf_info {
	Elf_Shdr     *sechdrs;
	Elf_Sym      *symtab_start;
	Elf_Sym      *symtab_stop;
	Elf_Section  export_sec;
	Elf_Section  export_gpl_sec;
	Elf_Section  export_gpl_future_sec;
	const char   *strtab;
	char	     *modinfo;
	unsigned int modinfo_len;