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) ...@@ -76,6 +76,22 @@ int init_module(void)
} }
EXPORT_SYMBOL(init_module); 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 */ /* Find a symbol, return value and the symbol group */
static unsigned long __find_symbol(const char *name, static unsigned long __find_symbol(const char *name,
struct kernel_symbol_group **group, struct kernel_symbol_group **group,
...@@ -878,45 +894,6 @@ void *__symbol_get(const char *symbol) ...@@ -878,45 +894,6 @@ void *__symbol_get(const char *symbol)
} }
EXPORT_SYMBOL_GPL(__symbol_get); 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. */ /* Change all symbols so that sh_value encodes the pointer directly. */
static int simplify_symbols(Elf_Shdr *sechdrs, static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex, unsigned int symindex,
...@@ -1106,93 +1083,16 @@ static struct module *load_module(void *umod, ...@@ -1106,93 +1083,16 @@ static struct module *load_module(void *umod,
sechdrs = (void *)hdr + hdr->e_shoff; sechdrs = (void *)hdr + hdr->e_shoff;
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 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++) { for (i = 1; i < hdr->e_shnum; i++) {
/* Mark all sections sh_addr with their address in the /* Mark all sections sh_addr with their address in the
temporary image. */ temporary image. */
sechdrs[i].sh_addr = (size_t)hdr + sechdrs[i].sh_offset; sechdrs[i].sh_addr = (size_t)hdr + sechdrs[i].sh_offset;
/* Internal symbols and strings. */
if (sechdrs[i].sh_type == SHT_SYMTAB) { if (sechdrs[i].sh_type == SHT_SYMTAB) {
/* Internal symbols */
DEBUGP("Symbol table in section %u\n", i);
symindex = i; symindex = i;
/* Strings */
strindex = sechdrs[i].sh_link; 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 #ifndef CONFIG_MODULE_UNLOAD
/* Don't load .exit sections */ /* Don't load .exit sections */
if (strstr(secstrings+sechdrs[i].sh_name, ".exit")) if (strstr(secstrings+sechdrs[i].sh_name, ".exit"))
...@@ -1200,6 +1100,14 @@ static struct module *load_module(void *umod, ...@@ -1200,6 +1100,14 @@ static struct module *load_module(void *umod,
#endif #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) { if (!modindex) {
printk(KERN_WARNING "No module found in object\n"); printk(KERN_WARNING "No module found in object\n");
err = -ENOEXEC; err = -ENOEXEC;
...@@ -1207,6 +1115,18 @@ static struct module *load_module(void *umod, ...@@ -1207,6 +1115,18 @@ static struct module *load_module(void *umod,
} }
mod = (void *)sechdrs[modindex].sh_addr; 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. */ /* Check module struct version now, before we try to use module. */
if (!check_modstruct_version(sechdrs, versindex, mod)) { if (!check_modstruct_version(sechdrs, versindex, mod)) {
err = -ENOEXEC; err = -ENOEXEC;
...@@ -1339,10 +1259,14 @@ static struct module *load_module(void *umod, ...@@ -1339,10 +1259,14 @@ static struct module *load_module(void *umod,
mod->extable.entry = (void *)sechdrs[exindex].sh_addr; mod->extable.entry = (void *)sechdrs[exindex].sh_addr;
} }
/* Now handle each section. */ /* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) { for (i = 1; i < hdr->e_shnum; i++) {
err = handle_section(secstrings + sechdrs[i].sh_name, if (sechdrs[i].sh_type == SHT_REL)
sechdrs, strindex, symindex, i, mod); 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) if (err < 0)
goto cleanup; 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