Commit 26c91ca0 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Modules code tidy up

Now that we search for 11 different sections by name, the if/else was
getting unwieldy.  Also, handle_section just does relocs, so it's a bit
of a misnomer, and it's best simply moved into the main code.

This open-codes handle_section, which simply does relocations now.

Also adds "find_sec" and uses it to find the various sections.
parent 69508a7c
......@@ -76,6 +76,22 @@ int init_module(void)
}
EXPORT_SYMBOL(init_module);
/* Find a module section: 0 means not found. */
static unsigned int find_sec(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs,
const char *secstrings,
const char *name)
{
unsigned int i;
for (i = 1; i < hdr->e_shnum; i++)
/* Alloc bit cleared means "ignore it." */
if ((sechdrs[i].sh_flags & SHF_ALLOC)
&& strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
return i;
return 0;
}
/* Find a symbol, return value and the symbol group */
static unsigned long __find_symbol(const char *name,
struct kernel_symbol_group **group,
......@@ -878,45 +894,6 @@ void *__symbol_get(const char *symbol)
}
EXPORT_SYMBOL_GPL(__symbol_get);
/* Deal with the given section */
static int handle_section(const char *name,
Elf_Shdr *sechdrs,
unsigned int strindex,
unsigned int symindex,
unsigned int i,
struct module *mod)
{
int ret;
const char *strtab = (char *)sechdrs[strindex].sh_addr;
switch (sechdrs[i].sh_type) {
case SHT_REL:
ret = apply_relocate(sechdrs, strtab, symindex, i, mod);
break;
case SHT_RELA:
ret = apply_relocate_add(sechdrs, strtab, symindex, i, mod);
break;
default:
DEBUGP("Ignoring section %u: %s\n", i,
sechdrs[i].sh_type==SHT_NULL ? "NULL":
sechdrs[i].sh_type==SHT_PROGBITS ? "PROGBITS":
sechdrs[i].sh_type==SHT_SYMTAB ? "SYMTAB":
sechdrs[i].sh_type==SHT_STRTAB ? "STRTAB":
sechdrs[i].sh_type==SHT_RELA ? "RELA":
sechdrs[i].sh_type==SHT_HASH ? "HASH":
sechdrs[i].sh_type==SHT_DYNAMIC ? "DYNAMIC":
sechdrs[i].sh_type==SHT_NOTE ? "NOTE":
sechdrs[i].sh_type==SHT_NOBITS ? "NOBITS":
sechdrs[i].sh_type==SHT_REL ? "REL":
sechdrs[i].sh_type==SHT_SHLIB ? "SHLIB":
sechdrs[i].sh_type==SHT_DYNSYM ? "DYNSYM":
sechdrs[i].sh_type==SHT_NUM ? "NUM":
"UNKNOWN");
ret = 0;
}
return ret;
}
/* Change all symbols so that sh_value encodes the pointer directly. */
static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex,
......@@ -1106,93 +1083,16 @@ static struct module *load_module(void *umod,
sechdrs = (void *)hdr + hdr->e_shoff;
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
/* May not export symbols, or have setup params, so these may
not exist */
exportindex = setupindex = obsparmindex = gplindex = licenseindex
= crcindex = gplcrcindex = versindex = 0;
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modindex = vmagindex = 0;
/* Find where important sections are */
for (i = 1; i < hdr->e_shnum; i++) {
/* Mark all sections sh_addr with their address in the
temporary image. */
sechdrs[i].sh_addr = (size_t)hdr + sechdrs[i].sh_offset;
/* Internal symbols and strings. */
if (sechdrs[i].sh_type == SHT_SYMTAB) {
/* Internal symbols */
DEBUGP("Symbol table in section %u\n", i);
symindex = i;
/* Strings */
strindex = sechdrs[i].sh_link;
DEBUGP("String table found in section %u\n", strindex);
} else if (strcmp(secstrings+sechdrs[i].sh_name,
".gnu.linkonce.this_module") == 0) {
/* The module struct */
DEBUGP("Module in section %u\n", i);
modindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__ksymtab")
== 0) {
/* Exported symbols. */
DEBUGP("EXPORT table in section %u\n", i);
exportindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__ksymtab_gpl") == 0) {
/* Exported symbols. (GPL) */
DEBUGP("GPL symbols found in section %u\n", i);
gplindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__kcrctab")
== 0) {
/* Exported symbols CRCs. */
DEBUGP("CRC table in section %u\n", i);
crcindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__kcrctab_gpl")
== 0) {
/* Exported symbols CRCs. (GPL)*/
DEBUGP("CRC table in section %u\n", i);
gplcrcindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__param")
== 0) {
/* Setup parameter info */
DEBUGP("Setup table found in section %u\n", i);
setupindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__ex_table")
== 0) {
/* Exception table */
DEBUGP("Exception table found in section %u\n", i);
exindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__obsparm")
== 0) {
/* Obsolete MODULE_PARM() table */
DEBUGP("Obsolete param found in section %u\n", i);
obsparmindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name,".init.license")
== 0) {
/* MODULE_LICENSE() */
DEBUGP("Licence found in section %u\n", i);
licenseindex = i;
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__vermagic") == 0 &&
(sechdrs[i].sh_flags & SHF_ALLOC)) {
/* Version magic. */
DEBUGP("Version magic found in section %u\n", i);
vmagindex = i;
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__versions") == 0 &&
(sechdrs[i].sh_flags & SHF_ALLOC)) {
/* Module version info (both exported and needed) */
DEBUGP("Versions found in section %u\n", i);
versindex = i;
sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
}
#ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */
if (sechdrs[i].sh_type == SHT_SYMTAB || i == strindex)
sechdrs[i].sh_flags |= SHF_ALLOC;
#endif
#ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */
if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
......@@ -1200,6 +1100,14 @@ static struct module *load_module(void *umod,
#endif
}
#ifdef CONFIG_KALLSYMS
/* Keep symbol and string tables for decoding later. */
sechdrs[symindex].sh_flags |= SHF_ALLOC;
sechdrs[strindex].sh_flags |= SHF_ALLOC;
#endif
modindex = find_sec(hdr, sechdrs, secstrings,
".gnu.linkonce.this_module");
if (!modindex) {
printk(KERN_WARNING "No module found in object\n");
err = -ENOEXEC;
......@@ -1207,6 +1115,18 @@ static struct module *load_module(void *umod,
}
mod = (void *)sechdrs[modindex].sh_addr;
/* Optional sections */
exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
licenseindex = find_sec(hdr, sechdrs, secstrings, ".init.license");
vmagindex = find_sec(hdr, sechdrs, secstrings, "__vermagic");
versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
/* Check module struct version now, before we try to use module. */
if (!check_modstruct_version(sechdrs, versindex, mod)) {
err = -ENOEXEC;
......@@ -1339,10 +1259,14 @@ static struct module *load_module(void *umod,
mod->extable.entry = (void *)sechdrs[exindex].sh_addr;
}
/* Now handle each section. */
/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
err = handle_section(secstrings + sechdrs[i].sh_name,
sechdrs, strindex, symindex, i, mod);
if (sechdrs[i].sh_type == SHT_REL)
err = apply_relocate(sechdrs, strtab, symindex, i,
mod);
else if (sechdrs[i].sh_type == SHT_RELA)
err = apply_relocate_add(sechdrs, strtab, symindex, i,
mod);
if (err < 0)
goto cleanup;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment