mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-03-30 19:15:14 +00:00
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: Andreas Gruenbacher <agruen@suse.de> Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Avantika Mathur <mathur@us.ibm.com> Signed-off-by: Valdis Kletnieks <valdis.kletnieks@vt.edu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
This commit is contained in:
parent
031ecc6de7
commit
bd5cbcedf4
2 changed files with 80 additions and 16 deletions
|
@ -22,6 +22,8 @@ int have_vmlinux = 0;
|
||||||
static int all_versions = 0;
|
static int all_versions = 0;
|
||||||
/* If we are modposting external module set to 1 */
|
/* If we are modposting external module set to 1 */
|
||||||
static int external_module = 0;
|
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, ...)
|
void fatal(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
@ -118,6 +120,7 @@ struct symbol {
|
||||||
unsigned int kernel:1; /* 1 if symbol is from kernel
|
unsigned int kernel:1; /* 1 if symbol is from kernel
|
||||||
* (only for external modules) **/
|
* (only for external modules) **/
|
||||||
unsigned int preloaded:1; /* 1 if symbol from Module.symvers */
|
unsigned int preloaded:1; /* 1 if symbol from Module.symvers */
|
||||||
|
enum export export; /* Type of export */
|
||||||
char name[0];
|
char name[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,7 +156,8 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For the hash of exported symbols */
|
/* 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;
|
unsigned int hash;
|
||||||
struct symbol *new;
|
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;
|
hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
|
||||||
new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
|
new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
|
||||||
new->module = module;
|
new->module = module;
|
||||||
|
new->export = export;
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,16 +184,55 @@ static struct symbol *find_symbol(const char *name)
|
||||||
return NULL;
|
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
|
* Add an exported symbol - it may have already been added without a
|
||||||
* CRC, in this case just update the CRC
|
* 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);
|
struct symbol *s = find_symbol(name);
|
||||||
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
s = new_symbol(name, mod);
|
s = new_symbol(name, mod, export);
|
||||||
} else {
|
} else {
|
||||||
if (!s->preloaded) {
|
if (!s->preloaded) {
|
||||||
warn("%s: '%s' exported twice. Previous export "
|
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->preloaded = 0;
|
||||||
s->vmlinux = is_vmlinux(mod->name);
|
s->vmlinux = is_vmlinux(mod->name);
|
||||||
s->kernel = 0;
|
s->kernel = 0;
|
||||||
|
s->export = export;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sym_update_crc(const char *name, struct module *mod,
|
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);
|
struct symbol *s = find_symbol(name);
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
s = new_symbol(name, mod);
|
s = new_symbol(name, mod, export);
|
||||||
s->crc = crc;
|
s->crc = crc;
|
||||||
s->crc_valid = 1;
|
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++) {
|
for (i = 1; i < hdr->e_shnum; i++) {
|
||||||
const char *secstrings
|
const char *secstrings
|
||||||
= (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
|
= (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
|
||||||
|
const char *secname;
|
||||||
|
|
||||||
if (sechdrs[i].sh_offset > info->size)
|
if (sechdrs[i].sh_offset > info->size)
|
||||||
goto truncated;
|
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 = (void *)hdr + sechdrs[i].sh_offset;
|
||||||
info->modinfo_len = sechdrs[i].sh_size;
|
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)
|
if (sechdrs[i].sh_type != SHT_SYMTAB)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -353,6 +406,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
|
||||||
Elf_Sym *sym, const char *symname)
|
Elf_Sym *sym, const char *symname)
|
||||||
{
|
{
|
||||||
unsigned int crc;
|
unsigned int crc;
|
||||||
|
enum export export = export_from_sec(info, sym->st_shndx);
|
||||||
|
|
||||||
switch (sym->st_shndx) {
|
switch (sym->st_shndx) {
|
||||||
case SHN_COMMON:
|
case SHN_COMMON:
|
||||||
|
@ -362,7 +416,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
|
||||||
/* CRC'd symbol */
|
/* CRC'd symbol */
|
||||||
if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
|
if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
|
||||||
crc = (unsigned int) sym->st_value;
|
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;
|
break;
|
||||||
case SHN_UNDEF:
|
case SHN_UNDEF:
|
||||||
|
@ -406,7 +461,8 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
|
||||||
default:
|
default:
|
||||||
/* All exported symbols */
|
/* All exported symbols */
|
||||||
if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
|
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)
|
if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
|
||||||
mod->has_init = 1;
|
mod->has_init = 1;
|
||||||
|
@ -1146,6 +1202,9 @@ static void write_if_changed(struct buffer *b, const char *fname)
|
||||||
fclose(file);
|
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)
|
static void read_dump(const char *fname, unsigned int kernel)
|
||||||
{
|
{
|
||||||
unsigned long size, pos = 0;
|
unsigned long size, pos = 0;
|
||||||
|
@ -1157,7 +1216,7 @@ static void read_dump(const char *fname, unsigned int kernel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ((line = get_next_line(&pos, file, size))) {
|
while ((line = get_next_line(&pos, file, size))) {
|
||||||
char *symname, *modname, *d;
|
char *symname, *modname, *d, *export;
|
||||||
unsigned int crc;
|
unsigned int crc;
|
||||||
struct module *mod;
|
struct module *mod;
|
||||||
struct symbol *s;
|
struct symbol *s;
|
||||||
|
@ -1168,8 +1227,9 @@ static void read_dump(const char *fname, unsigned int kernel)
|
||||||
if (!(modname = strchr(symname, '\t')))
|
if (!(modname = strchr(symname, '\t')))
|
||||||
goto fail;
|
goto fail;
|
||||||
*modname++ = '\0';
|
*modname++ = '\0';
|
||||||
if (strchr(modname, '\t'))
|
if (!(export = strchr(modname, '\t')))
|
||||||
goto fail;
|
*export++ = '\0';
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1181,10 +1241,10 @@ static void read_dump(const char *fname, unsigned int kernel)
|
||||||
mod = new_module(NOFAIL(strdup(modname)));
|
mod = new_module(NOFAIL(strdup(modname)));
|
||||||
mod->skip = 1;
|
mod->skip = 1;
|
||||||
}
|
}
|
||||||
s = sym_add_exported(symname, mod);
|
s = sym_add_exported(symname, mod, export_no(export));
|
||||||
s->kernel = kernel;
|
s->kernel = kernel;
|
||||||
s->preloaded = 1;
|
s->preloaded = 1;
|
||||||
sym_update_crc(symname, mod, crc);
|
sym_update_crc(symname, mod, crc, export_no(export));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
fail:
|
fail:
|
||||||
|
@ -1214,9 +1274,10 @@ static void write_dump(const char *fname)
|
||||||
symbol = symbolhash[n];
|
symbol = symbolhash[n];
|
||||||
while (symbol) {
|
while (symbol) {
|
||||||
if (dump_sym(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->crc, symbol->name,
|
||||||
symbol->module->name);
|
symbol->module->name,
|
||||||
|
export_str(symbol->export));
|
||||||
symbol = symbol->next;
|
symbol = symbol->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,9 @@ struct elf_info {
|
||||||
Elf_Shdr *sechdrs;
|
Elf_Shdr *sechdrs;
|
||||||
Elf_Sym *symtab_start;
|
Elf_Sym *symtab_start;
|
||||||
Elf_Sym *symtab_stop;
|
Elf_Sym *symtab_stop;
|
||||||
|
Elf_Section export_sec;
|
||||||
|
Elf_Section export_gpl_sec;
|
||||||
|
Elf_Section export_gpl_future_sec;
|
||||||
const char *strtab;
|
const char *strtab;
|
||||||
char *modinfo;
|
char *modinfo;
|
||||||
unsigned int modinfo_len;
|
unsigned int modinfo_len;
|
||||||
|
|
Loading…
Add table
Reference in a new issue