diff options
author | Andreas Robinson <andr345@gmail.com> | 2009-05-14 18:22:23 +0200 |
---|---|---|
committer | Andreas Robinson <andr345@gmail.com> | 2009-05-15 15:44:54 +0200 |
commit | 45ec2644e6970f28fbf2acc789391de3e649f154 (patch) | |
tree | 187c58aadca71636fab1ae6e3774039cf1d8b767 | |
parent | d1e6992067f6b06b572430d1ea90d88ec87f4221 (diff) | |
download | module-init-tools-45ec2644e6970f28fbf2acc789391de3e649f154.tar.gz |
modprobe, elfops: move strip_section() to elfops and refactor it
strip_section() now finds the section flags with get_section()
and handles files of opposite endianness.
Signed-off-by: Andreas Robinson <andr345@gmail.com>
-rw-r--r-- | elfops.h | 1 | ||||
-rw-r--r-- | elfops_core.c | 22 | ||||
-rw-r--r-- | modprobe.c | 46 |
3 files changed, 25 insertions, 44 deletions
@@ -65,6 +65,7 @@ struct module_ops struct module_tables *tables); char *(*get_aliases)(struct elf_file *module, unsigned long *size); char *(*get_modinfo)(struct elf_file *module, unsigned long *size); + void (*strip_section)(struct elf_file *module, const char *secname); }; extern struct module_ops mod_ops32, mod_ops64; diff --git a/elfops_core.c b/elfops_core.c index 64e353a..14eef96 100644 --- a/elfops_core.c +++ b/elfops_core.c @@ -3,12 +3,16 @@ #define PERBIT(x) x##32 #define ElfPERBIT(x) Elf32_##x #define ELFPERBIT(x) ELF32_##x +/* 32-bit unsigned integer */ +#define Elf32_Uint Elf32_Word #elif defined(ELF64BIT) #define PERBIT(x) x##64 #define ElfPERBIT(x) Elf64_##x #define ELFPERBIT(x) ELF64_##x +/* 64-bit unsigned integer */ +#define Elf64_Uint Elf64_Xword #else # error "Undefined ELF word length" @@ -297,6 +301,23 @@ static void PERBIT(fetch_tables)(struct elf_file *module, } } +/* + * strip_section - tell the kernel to ignore the named section + */ +static void PERBIT(strip_section)(struct elf_file *module, const char *secname) +{ + void *p; + ElfPERBIT(Shdr) *sechdr; + unsigned long secsize; + + p = PERBIT(get_section)(module, secname, &sechdr, &secsize); + if (p) { + ElfPERBIT(Uint) mask; + mask = ~((ElfPERBIT(Uint))SHF_ALLOC); + sechdr->sh_flags &= END(mask, module->conv); + } +} + struct module_ops PERBIT(mod_ops) = { .load_section = PERBIT(load_section), .load_symbols = PERBIT(load_symbols), @@ -304,6 +325,7 @@ struct module_ops PERBIT(mod_ops) = { .fetch_tables = PERBIT(fetch_tables), .get_aliases = PERBIT(get_aliases), .get_modinfo = PERBIT(get_modinfo), + .strip_section = PERBIT(strip_section), }; #undef PERBIT @@ -324,55 +324,13 @@ static void rename_module(struct elf_file *module, replace_modname(module, modstruct, len, oldname, newname); } -/* Kernel told to ignore these sections if SHF_ALLOC not set. */ -static void invalidate_section32(struct elf_file *module, const char *secname) -{ - void *mod = module->data; - Elf32_Ehdr *hdr = mod; - Elf32_Shdr *sechdrs = mod + hdr->e_shoff; - const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset; - unsigned int i; - - for (i = 1; i < hdr->e_shnum; i++) - if (streq(secnames+sechdrs[i].sh_name, secname)) - sechdrs[i].sh_flags &= ~SHF_ALLOC; -} - -static void invalidate_section64(struct elf_file *module, const char *secname) -{ - void *mod = module->data; - Elf64_Ehdr *hdr = mod; - Elf64_Shdr *sechdrs = mod + hdr->e_shoff; - const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset; - unsigned int i; - - for (i = 1; i < hdr->e_shnum; i++) - if (streq(secnames+sechdrs[i].sh_name, secname)) - sechdrs[i].sh_flags &= ~(unsigned long long)SHF_ALLOC; -} - -static void strip_section(struct elf_file *module, const char *secname) -{ - switch (elf_ident(module->data, module->len, NULL)) { - case ELFCLASS32: - invalidate_section32(module, secname); - break; - case ELFCLASS64: - invalidate_section64(module, secname); - break; - default: - warn("Unknown module format in %s: not forcing version\n", - module->pathname); - } -} - static void clear_magic(struct elf_file *module) { const char *p; unsigned long len; /* Old-style: __vermagic section */ - strip_section(module, "__vermagic"); + module->ops->strip_section(module, "__vermagic"); /* New-style: in .modinfo section */ p = module->ops->get_modinfo(module, &len); @@ -731,7 +689,7 @@ static int insmod(struct list_head *list, if (newname) rename_module(module, mod->modname, newname); if (strip_modversion) - strip_section(module, "__versions"); + module->ops->strip_section(module, "__versions"); if (strip_vermagic) clear_magic(module); |