Signed-off-by: Andreas Robinson <andr345@xxxxxxxxx> --- elfops.c | 9 +++++++++ elfops.h | 14 ++++++++++++++ elfops_core.c | 25 +++++++++++++++++++++++++ modprobe.c | 55 ++----------------------------------------------------- 4 files changed, 50 insertions(+), 53 deletions(-) diff --git a/elfops.c b/elfops.c index 3872bf8..0fb492f 100644 --- a/elfops.c +++ b/elfops.c @@ -19,6 +19,15 @@ static const char *weak_sym = "W"; static const char *undef_sym = "U"; +/* dump_modversions helper */ +static const char *skip_dot(const char *str) +{ + /* For our purposes, .foo matches foo. PPC64 needs this. */ + if (str && str[0] == '.') + return str + 1; + return str; +} + #define ELF32BIT #include "elfops_core.c" #undef ELF32BIT diff --git a/elfops.h b/elfops.h index c33793a..e131da0 100644 --- a/elfops.h +++ b/elfops.h @@ -1,6 +1,7 @@ #ifndef MODINITTOOLS_MODULEOPS_H #define MODINITTOOLS_MODULEOPS_H #include <stdio.h> +#include <stdint.h> /* All the icky stuff to do with manipulating 64 and 32-bit modules belongs here. */ @@ -14,6 +15,18 @@ struct kernel_symbol64 { char name[64 - 8]; }; +struct modver_info32 +{ + uint32_t crc; + char name[64 - sizeof(uint32_t)]; +}; + +struct modver_info64 +{ + uint64_t crc; + char name[64 - sizeof(uint64_t)]; +}; + struct elf_file { char *pathname; @@ -66,6 +79,7 @@ struct module_ops 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); + int (*dump_modvers)(struct elf_file *module); }; extern struct module_ops mod_ops32, mod_ops64; diff --git a/elfops_core.c b/elfops_core.c index 14eef96..39fd4c3 100644 --- a/elfops_core.c +++ b/elfops_core.c @@ -318,6 +318,30 @@ static void PERBIT(strip_section)(struct elf_file *module, const char *secname) } } +static int PERBIT(dump_modversions)(struct elf_file *module) +{ + unsigned long secsize; + struct PERBIT(modver_info) *info; + int n = 0; + + info = module->ops->load_section(module, "__versions", &secsize); + if (!info) + return 0; /* not a kernel module */ + if (secsize % sizeof(*info) != 0) + return -1; /* invalid section size */ + + for (n = 0; n < secsize / sizeof(*info); n++) { +#if defined(ELF32BIT) + printf("0x%08lx\t%s\n", (unsigned long) +#else /* defined(ELF64BIT) */ + printf("0x%08llx\t%s\n", (unsigned long long) +#endif + END(info[n].crc, module->conv), + skip_dot(info[n].name)); + } + return n; +} + struct module_ops PERBIT(mod_ops) = { .load_section = PERBIT(load_section), .load_symbols = PERBIT(load_symbols), @@ -326,6 +350,7 @@ struct module_ops PERBIT(mod_ops) = { .get_aliases = PERBIT(get_aliases), .get_modinfo = PERBIT(get_modinfo), .strip_section = PERBIT(strip_section), + .dump_modvers = PERBIT(dump_modversions), }; #undef PERBIT diff --git a/modprobe.c b/modprobe.c index a351a58..c6ef155 100644 --- a/modprobe.c +++ b/modprobe.c @@ -792,71 +792,20 @@ nonexistent_module: goto remove_rest; } -struct modver32_info -{ - uint32_t crc; - char name[64 - sizeof(uint32_t)]; -}; - -struct modver64_info -{ - uint64_t crc; - char name[64 - sizeof(uint64_t)]; -}; - -const char *skip_dot(const char *str) -{ - /* For our purposes, .foo matches foo. PPC64 needs this. */ - if (str && str[0] == '.') - return str + 1; - return str; -} - void dump_modversions(const char *filename, errfn_t error) { struct elf_file *module; - unsigned long secsize; - void *info; - struct modver32_info *info32; - struct modver64_info *info64; - int n; module = grab_elf_file(filename); if (!module) { error("%s: %s\n", filename, strerror(errno)); return; } - info = module->ops->load_section(module, "__versions", &secsize); - if (!info) - goto done; /* Does not seem to be a kernel module */ - - switch (elf_ident(module->data, module->len, NULL)) { - case ELFCLASS32: - info32 = info; - if (secsize % sizeof(struct modver32_info)) - error("Wrong section size in %s\n", filename); - for (n = 0; n < secsize / sizeof(struct modver32_info); n++) - printf("0x%08lx\t%s\n", (unsigned long) - info32[n].crc, skip_dot(info32[n].name)); - break; - - case ELFCLASS64: - info64 = info; - if (secsize % sizeof(struct modver64_info)) - error("Wrong section size in %s\n", filename); - for (n = 0; n < secsize / sizeof(struct modver64_info); n++) - printf("0x%08llx\t%s\n", (unsigned long long) - info64[n].crc, skip_dot(info64[n].name)); - break; - - default: - error("%s: ELF class not recognized\n", filename); - } -done: + if (module->ops->dump_modvers(module) < 0) + error("Wrong section size in '%s'\n", filename); release_elf_file(module); } - /* Does path contain directory(s) subpath? */ static int type_matches(const char *path, const char *subpath) { -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-modules" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html