diff options
author | Andreas Robinson <andr345@gmail.com> | 2009-05-10 11:38:11 +0200 |
---|---|---|
committer | Andreas Robinson <andr345@gmail.com> | 2009-05-12 12:55:40 +0200 |
commit | 4ac9bc5b709b8a665e828e9543fdf65119beba7e (patch) | |
tree | 83bc4b6664dba2415f71fb86dd475a7f41aecd92 | |
parent | 90822ab233d2bbd347bdfaac4be407e924dbd5ae (diff) | |
download | module-init-tools-4ac9bc5b709b8a665e828e9543fdf65119beba7e.tar.gz |
move ELF-related code into elfops
Specifically
depmod.h => elfops.h: struct module_tables and struct elf_file
elfops.c => elfops_core.c: X-macros (eg PERBIT)
elf_core.c => elfops_core.c: get_section()
util.[ch] => elfops.[ch]: elf_ident() and get_section()
Additionally, elf_core.c is deleted, being replaced by elfops_core.c
Signed-off-by: Andreas Robinson <andr345@gmail.com>
-rw-r--r-- | depmod.h | 39 | ||||
-rw-r--r-- | elf_core.c | 43 | ||||
-rw-r--r-- | elfops.c | 46 | ||||
-rw-r--r-- | elfops.h | 46 | ||||
-rw-r--r-- | elfops_core.c | 63 | ||||
-rw-r--r-- | modinfo.c | 1 | ||||
-rw-r--r-- | modprobe.c | 1 | ||||
-rw-r--r-- | util.c | 45 | ||||
-rw-r--r-- | util.h | 8 |
9 files changed, 149 insertions, 143 deletions
@@ -1,44 +1,7 @@ #ifndef MODINITTOOLS_DEPMOD_H #define MODINITTOOLS_DEPMOD_H #include "list.h" - -/* Tables extracted from module by ops->fetch_tables(). */ -struct module_tables { - unsigned int pci_size; - void *pci_table; - unsigned int usb_size; - void *usb_table; - unsigned int ieee1394_size; - void *ieee1394_table; - unsigned int ccw_size; - void *ccw_table; - unsigned int pnp_size; - void *pnp_table; - unsigned int pnp_card_size; - unsigned int pnp_card_offset; - void *pnp_card_table; - unsigned int input_size; - void *input_table; - unsigned int input_table_size; - unsigned int serio_size; - void *serio_table; - unsigned int of_size; - void *of_table; -}; - -struct elf_file -{ - /* File operations */ - struct module_ops *ops; - - /* Convert endian? */ - int conv; - - /* File contents and length. */ - void *data; - unsigned long len; -}; - +#include "elfops.h" struct module; diff --git a/elf_core.c b/elf_core.c deleted file mode 100644 index 1525c36..0000000 --- a/elf_core.c +++ /dev/null @@ -1,43 +0,0 @@ -void *PERBIT(get_section)(void *file, - unsigned long fsize, - const char *secname, - unsigned long *secsize, - int conv) -{ - ElfPERBIT(Ehdr) *hdr; - ElfPERBIT(Shdr) *sechdrs; - ElfPERBIT(Off) e_shoff; - ElfPERBIT(Half) e_shnum, e_shstrndx; - - const char *secnames; - unsigned int i; - - if (fsize > 0 && fsize < sizeof(*hdr)) - return NULL; - - hdr = file; - e_shoff = END(hdr->e_shoff, conv); - e_shnum = END(hdr->e_shnum, conv); - e_shstrndx = END(hdr->e_shstrndx, conv); - - if (fsize > 0 && fsize < e_shoff + e_shnum * sizeof(sechdrs[0])) - return NULL; - - sechdrs = file + e_shoff; - - if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv)) - return NULL; - - /* Find section by name, return pointer and size. */ - - secnames = file + END(sechdrs[e_shstrndx].sh_offset, conv); - for (i = 1; i < e_shnum; i++) { - if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) { - *secsize = END(sechdrs[i].sh_size, conv); - return file + END(sechdrs[i].sh_offset, conv); - } - } - *secsize = 0; - return NULL; -} - @@ -11,15 +11,43 @@ #include "elfops.h" #include "tables.h" -#define PERBIT(x) x##32 -#define ElfPERBIT(x) Elf32_##x -#define ELFPERBIT(x) ELF32_##x +#define ELF32BIT #include "elfops_core.c" +#undef ELF32BIT -#undef PERBIT -#undef ElfPERBIT -#undef ELFPERBIT -#define PERBIT(x) x##64 -#define ElfPERBIT(x) Elf64_##x -#define ELFPERBIT(x) ELF64_##x +#define ELF64BIT #include "elfops_core.c" +#undef ELF64BIT + +/* + * Check ELF file header. + */ +int elf_ident(void *file, unsigned long fsize, int *conv) +{ + /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */ + unsigned char *ident = file; + + if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0) + return -ENOEXEC; /* Not an ELF object */ + if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2) + return -EINVAL; /* Unknown endianness */ + + if (conv != NULL) + *conv = native_endianness() != ident[EI_DATA]; + return ident[EI_CLASS]; +} + +void *get_section(void *file, unsigned long filesize, + const char *secname, unsigned long *secsize) +{ + int conv; + + switch (elf_ident(file, filesize, &conv)) { + case ELFCLASS32: + return get_section32(file, filesize, secname, secsize, conv); + case ELFCLASS64: + return get_section64(file, filesize, secname, secsize, conv); + default: + return NULL; + } +} @@ -14,6 +14,44 @@ struct kernel_symbol64 { char name[64 - 8]; }; +struct elf_file +{ + /* File operations */ + struct module_ops *ops; + + /* Convert endian? */ + int conv; + + /* File contents and length. */ + void *data; + unsigned long len; +}; + +/* Tables extracted from module by ops->fetch_tables(). */ +struct module_tables +{ + unsigned int pci_size; + void *pci_table; + unsigned int usb_size; + void *usb_table; + unsigned int ieee1394_size; + void *ieee1394_table; + unsigned int ccw_size; + void *ccw_table; + unsigned int pnp_size; + void *pnp_table; + unsigned int pnp_card_size; + unsigned int pnp_card_offset; + void *pnp_card_table; + unsigned int input_size; + void *input_table; + unsigned int input_table_size; + unsigned int serio_size; + void *serio_table; + unsigned int of_size; + void *of_table; +}; + struct module_ops { struct string_table *(*load_strings)(struct elf_file *module, @@ -29,4 +67,12 @@ struct module_ops extern struct module_ops mod_ops32, mod_ops64; +int elf_ident(void *file, unsigned long fsize, int *conv); +void *get_section(void *file, unsigned long filesize, + const char *secname, unsigned long *secsize); +void *get_section32(void *file, unsigned long filesize, + const char *secname, unsigned long *secsize, int conv); +void *get_section64(void *file, unsigned long filesize, + const char *secname, unsigned long *secsize, int conv); + #endif /* MODINITTOOLS_MODULEOPS_H */ diff --git a/elfops_core.c b/elfops_core.c index 4649b3f..8e6f37e 100644 --- a/elfops_core.c +++ b/elfops_core.c @@ -1,3 +1,62 @@ +#if defined(ELF32BIT) + +#define PERBIT(x) x##32 +#define ElfPERBIT(x) Elf32_##x +#define ELFPERBIT(x) ELF32_##x + +#elif defined(ELF64BIT) + +#define PERBIT(x) x##64 +#define ElfPERBIT(x) Elf64_##x +#define ELFPERBIT(x) ELF64_##x + +#else +# error "Undefined ELF word length" +#endif + +void *PERBIT(get_section)(void *file, + unsigned long fsize, + const char *secname, + unsigned long *secsize, + int conv) +{ + ElfPERBIT(Ehdr) *hdr; + ElfPERBIT(Shdr) *sechdrs; + ElfPERBIT(Off) e_shoff; + ElfPERBIT(Half) e_shnum, e_shstrndx; + + const char *secnames; + unsigned int i; + + if (fsize > 0 && fsize < sizeof(*hdr)) + return NULL; + + hdr = file; + e_shoff = END(hdr->e_shoff, conv); + e_shnum = END(hdr->e_shnum, conv); + e_shstrndx = END(hdr->e_shstrndx, conv); + + if (fsize > 0 && fsize < e_shoff + e_shnum * sizeof(sechdrs[0])) + return NULL; + + sechdrs = file + e_shoff; + + if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv)) + return NULL; + + /* Find section by name, return pointer and size. */ + + secnames = file + END(sechdrs[e_shstrndx].sh_offset, conv); + for (i = 1; i < e_shnum; i++) { + if (streq(secnames + END(sechdrs[i].sh_name, conv), secname)) { + *secsize = END(sechdrs[i].sh_size, conv); + return file + END(sechdrs[i].sh_offset, conv); + } + } + *secsize = 0; + return NULL; +} + /* Load the given section: NULL on error. */ static void *PERBIT(load_section)(struct elf_file *module, const char *secname, @@ -238,3 +297,7 @@ struct module_ops PERBIT(mod_ops) = { .get_aliases = PERBIT(get_aliases), .get_modinfo = PERBIT(get_modinfo), }; + +#undef PERBIT +#undef ElfPERBIT +#undef ELFPERBIT @@ -14,6 +14,7 @@ #include <sys/mman.h> #include "util.h" +#include "elfops.h" #include "zlibsupport.h" #include "testing.h" @@ -40,6 +40,7 @@ #include <syslog.h> #include "util.h" +#include "elfops.h" #include "zlibsupport.h" #include "logging.h" #include "index.h" @@ -190,48 +190,3 @@ int __attribute__ ((pure)) native_endianness() return (char) *((uint32_t*)("\1\0\0\2")); } -/* - * Check ELF file header. - */ -int elf_ident(void *file, unsigned long fsize, int *conv) -{ - /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */ - unsigned char *ident = file; - - if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0) - return -ENOEXEC; /* Not an ELF object */ - if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2) - return -EINVAL; /* Unknown endianness */ - - if (conv != NULL) - *conv = native_endianness() != ident[EI_DATA]; - return ident[EI_CLASS]; -} - -#define PERBIT(x) x##32 -#define ElfPERBIT(x) Elf32_##x -#define ELFPERBIT(x) ELF32_##x -#include "elf_core.c" - -#undef PERBIT -#undef ElfPERBIT -#undef ELFPERBIT -#define PERBIT(x) x##64 -#define ElfPERBIT(x) Elf64_##x -#define ELFPERBIT(x) ELF64_##x -#include "elf_core.c" - -void *get_section(void *file, unsigned long filesize, - const char *secname, unsigned long *secsize) -{ - int conv; - - switch (elf_ident(file, filesize, &conv)) { - case ELFCLASS32: - return get_section32(file, filesize, secname, secsize, conv); - case ELFCLASS64: - return get_section64(file, filesize, secname, secsize, conv); - default: - return NULL; - } -} @@ -40,14 +40,6 @@ static inline void __swap_bytes(const void *src, void *dest, unsigned int size) int native_endianness(void); -int elf_ident(void *file, unsigned long fsize, int *conv); -void *get_section(void *file, unsigned long filesize, - const char *secname, unsigned long *secsize); -void *get_section32(void *file, unsigned long filesize, - const char *secname, unsigned long *secsize, int conv); -void *get_section64(void *file, unsigned long filesize, - const char *secname, unsigned long *secsize, int conv); - #define streq(a,b) (strcmp((a),(b)) == 0) #define strstarts(a,start) (strncmp((a),(start), strlen(start)) == 0) |