diff options
author | Jon Masters <jcm@jonmasters.org> | 2009-05-19 04:50:10 -0400 |
---|---|---|
committer | Jon Masters <jcm@jonmasters.org> | 2009-05-19 04:50:10 -0400 |
commit | 2d23075ca0f6560901ddda3645ba49d4c330a867 (patch) | |
tree | ea89f07256f93faabfe1e26108364bae3825e0a2 | |
parent | aa6fe1585412d5ad603fc81b7075dffb93a8b8f2 (diff) | |
parent | 4646064c0335e9c71c9124bacabd6b5e2827e3e9 (diff) | |
download | module-init-tools-2d23075ca0f6560901ddda3645ba49d4c330a867.tar.gz |
Merge branch 'elf_cleanup2' of ../module_init_tools_andr345
-rw-r--r-- | depmod.c | 42 | ||||
-rw-r--r-- | depmod.h | 2 | ||||
-rw-r--r-- | elfops.c | 98 | ||||
-rw-r--r-- | elfops.h | 31 | ||||
-rw-r--r-- | elfops_core.c | 87 | ||||
-rw-r--r-- | logging.h | 6 | ||||
-rw-r--r-- | modinfo.c | 120 | ||||
-rw-r--r-- | modprobe.c | 180 | ||||
-rw-r--r-- | tables.c | 19 |
9 files changed, 305 insertions, 280 deletions
@@ -264,7 +264,6 @@ static int ends_in(const char *name, const char *ext) static struct module *grab_module(const char *dirname, const char *filename) { struct module *new; - struct elf_file *file; new = NOFAIL(malloc(sizeof(*new) + strlen(dirname?:"") + 1 + strlen(filename) + 1)); @@ -277,39 +276,14 @@ static struct module *grab_module(const char *dirname, const char *filename) INIT_LIST_HEAD(&new->dep_list); new->order = INDEX_PRIORITY_MIN; - file = &new->file; - - file->data = grab_file(new->pathname, &file->len); - if (!file->data) { + new->file = grab_elf_file(new->pathname); + if (!new->file) { warn("Can't read module %s: %s\n", new->pathname, strerror(errno)); - goto fail_data; + free(new); + return NULL; } - - switch (elf_ident(file->data, file->len, &file->conv)) { - case ELFCLASS32: - file->ops = &mod_ops32; - break; - case ELFCLASS64: - file->ops = &mod_ops64; - break; - case -ENOEXEC: - warn("Module %s is not an elf object\n", new->pathname); - goto fail; - case -EINVAL: - warn("Module %s has unknown endianness\n", new->pathname); - goto fail; - default: - warn("Module %s has unknown word size\n", new->pathname); - goto fail; - } return new; - -fail: - release_file(file->data, new->file.len); -fail_data: - free(new); - return NULL; } struct module_traverse @@ -680,7 +654,7 @@ static void calculate_deps(struct module *module) module->num_deps = 0; module->deps = NULL; - file = &module->file; + file = module->file; symnames = file->ops->load_dep_syms(module->pathname, file, &symtypes); if (!symnames || !symtypes) @@ -714,7 +688,7 @@ static struct module *parse_modules(struct module *list) int j; for (i = list; i; i = i->next) { - file = &i->file; + file = i->file; syms = file->ops->load_symbols(file); if (syms) { for (j = 0; j < syms->cnt; j++) @@ -803,7 +777,7 @@ static void output_aliases(struct module *modules, FILE *out, char *dirname) for (i = modules; i; i = i->next) { char modname[strlen(i->pathname)+1]; - file = &i->file; + file = i->file; filename2modname(modname, i->pathname); /* Grab from old-style .modalias section. */ @@ -838,7 +812,7 @@ static void output_aliases_bin(struct module *modules, FILE *out, char *dirname) for (i = modules; i; i = i->next) { char modname[strlen(i->pathname)+1]; - file = &i->file; + file = i->file; filename2modname(modname, i->pathname); /* Grab from old-style .modalias section. */ @@ -23,7 +23,7 @@ struct module /* Tables extracted from module by ops->fetch_tables(). */ struct module_tables tables; - struct elf_file file; + struct elf_file *file; char *basename; /* points into pathname */ char pathname[0]; @@ -5,16 +5,29 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <fcntl.h> #include "depmod.h" #include "util.h" #include "logging.h" #include "elfops.h" #include "tables.h" +#include "zlibsupport.h" + +#include "testing.h" /* Symbol types, returned by load_dep_syms */ 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 @@ -26,7 +39,7 @@ static const char *undef_sym = "U"; /* * Check ELF file header. */ -int elf_ident(void *file, unsigned long fsize, int *conv) +static 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; @@ -41,17 +54,84 @@ int elf_ident(void *file, unsigned long fsize, int *conv) return ident[EI_CLASS]; } -void *get_section(void *file, unsigned long filesize, - const char *secname, unsigned long *secsize) +/* + * grab_elf_file - read ELF file into memory + * @pathame: file to load + * + * Returns NULL, and errno set on error. + */ +struct elf_file *grab_elf_file(const char *pathname) +{ + int fd; + int err; + struct elf_file *file; + + fd = open(pathname, O_RDONLY, 0); + if (fd < 0) + return NULL; + file = grab_elf_file_fd(pathname, fd); + + err = errno; + close(fd); + errno = err; + return file; +} + +/* + * grab_elf_file_fd - read ELF file from file descriptor into memory + * @pathame: name of file to load + * @fd: file descriptor of file to load + * + * Returns NULL, and errno set on error. + */ +struct elf_file *grab_elf_file_fd(const char *pathname, int fd) { - int conv; + struct elf_file *file; - switch (elf_ident(file, filesize, &conv)) { + file = malloc(sizeof(*file)); + if (!file) { + errno = ENOMEM; + return NULL; + } + file->pathname = strdup(pathname); + if (!file->pathname) { + free(file); + errno = ENOMEM; + return NULL; + } + file->data = grab_fd(fd, &file->len); + if (!file->data) + goto fail; + + switch (elf_ident(file->data, file->len, &file->conv)) { case ELFCLASS32: - return get_section32(file, filesize, secname, secsize, conv); + file->ops = &mod_ops32; + break; case ELFCLASS64: - return get_section64(file, filesize, secname, secsize, conv); - default: - return NULL; + file->ops = &mod_ops64; + break; + case -ENOEXEC: /* Not an ELF object */ + case -EINVAL: /* Unknown endianness */ + default: /* Unknown word size */ + errno = ENOEXEC; + goto fail; } + return file; +fail: + release_elf_file(file); + return NULL; +} + +void release_elf_file(struct elf_file *file) +{ + int err = errno; + + if (!file) + return; + + release_file(file->data, file->len); + free(file->pathname); + free(file); + + errno = err; } @@ -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,8 +15,22 @@ 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; + /* File operations */ struct module_ops *ops; @@ -54,8 +69,8 @@ struct module_tables struct module_ops { - struct string_table *(*load_strings)(struct elf_file *module, - const char *secname, struct string_table *tbl); + void *(*load_section)(struct elf_file *module, + const char *secname, unsigned long *secsize); struct string_table *(*load_symbols)(struct elf_file *module); struct string_table *(*load_dep_syms)(const char *pathname, struct elf_file *module, struct string_table **types); @@ -63,16 +78,14 @@ 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); + int (*dump_modvers)(struct elf_file *module); }; 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); +struct elf_file *grab_elf_file(const char *pathname); +struct elf_file *grab_elf_file_fd(const char *pathname, int fd); +void release_elf_file(struct elf_file *file); #endif /* MODINITTOOLS_MODULEOPS_H */ diff --git a/elfops_core.c b/elfops_core.c index 8b7f4de..39fd4c3 100644 --- a/elfops_core.c +++ b/elfops_core.c @@ -3,54 +3,66 @@ #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" #endif -void *PERBIT(get_section)(void *file, - unsigned long fsize, - const char *secname, - unsigned long *secsize, - int conv) +static void *PERBIT(get_section)(struct elf_file *module, + const char *secname, + ElfPERBIT(Shdr) **sechdr, + unsigned long *secsize) { + void *data = module->data; + unsigned long len = module->len; + int conv = module->conv; + ElfPERBIT(Ehdr) *hdr; ElfPERBIT(Shdr) *sechdrs; ElfPERBIT(Off) e_shoff; ElfPERBIT(Half) e_shnum, e_shstrndx; + ElfPERBIT(Off) secoffset; const char *secnames; unsigned int i; - if (fsize > 0 && fsize < sizeof(*hdr)) + if (len <= 0 || len < sizeof(*hdr)) return NULL; - hdr = file; + hdr = data; 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])) + if (len < e_shoff + e_shnum * sizeof(sechdrs[0])) return NULL; - sechdrs = file + e_shoff; + sechdrs = data + e_shoff; - if (fsize > 0 && fsize < END(sechdrs[e_shstrndx].sh_offset, conv)) + if (len < 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); + /* Find section by name; return header, pointer and size. */ + secnames = data + 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); + secoffset = END(sechdrs[i].sh_offset, conv); + if (sechdr) + *sechdr = sechdrs + i; + if (len < secoffset + *secsize) + return NULL; + return data + secoffset; } } *secsize = 0; @@ -62,7 +74,7 @@ static void *PERBIT(load_section)(struct elf_file *module, const char *secname, unsigned long *secsize) { - return PERBIT(get_section)(module->data, 0, secname, secsize, module->conv); + return PERBIT(get_section)(module, secname, NULL, secsize); } static struct string_table *PERBIT(load_strings)(struct elf_file *module, @@ -289,13 +301,56 @@ 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); + } +} + +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_strings = PERBIT(load_strings), + .load_section = PERBIT(load_section), .load_symbols = PERBIT(load_symbols), .load_dep_syms = PERBIT(load_dep_syms), .fetch_tables = PERBIT(fetch_tables), .get_aliases = PERBIT(get_aliases), .get_modinfo = PERBIT(get_modinfo), + .strip_section = PERBIT(strip_section), + .dump_modvers = PERBIT(dump_modversions), }; #undef PERBIT @@ -27,8 +27,10 @@ static inline void grammar(const char *cmd, #define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr) -#define nofail_asprintf(ptr, ...) \ - { if (asprintf((ptr), __VA_ARGS__) < 0) do_nofail(NULL, __FILE__, __LINE__, #ptr); } +#define nofail_asprintf(ptr, ...) \ + do { if (asprintf((ptr), __VA_ARGS__) < 0) \ + do_nofail(NULL, __FILE__, __LINE__, #ptr); \ + } while(0) static inline void *do_nofail(void *ptr, const char *file, int line, const char *expr) { @@ -14,6 +14,7 @@ #include <sys/mman.h> #include "util.h" +#include "logging.h" #include "elfops.h" #include "zlibsupport.h" #include "testing.h" @@ -38,7 +39,7 @@ static struct param *add_param(const char *name, struct param **list) for (i = *list; i; i = i->next) if (strncmp(i->name, name, namelen) == 0) return i; - i = malloc(sizeof(*i) + namelen+1); + i = NOFAIL(malloc(sizeof(*i) + namelen+1)); strncpy((char *)(i + 1), name, namelen); ((char *)(i + 1))[namelen] = '\0'; i->name = (char *)(i + 1); @@ -178,85 +179,71 @@ static char *next_line(char *p, const char *end) return (char *)end + 1; } -static void *grab_module(const char *name, unsigned long *size, char**filename, - const char *kernel, const char *basedir) +static struct elf_file *grab_module(const char *name, + const char *kernel, + const char *basedir) { char *data; + unsigned long size; struct utsname buf; char *depname, *p, *moddir; + struct elf_file *module; if (strchr(name, '.') || strchr(name, '/')) { - data = grab_file(name, size); - if (data) { - *filename = strdup(name); - return data; - } else { - fprintf(stderr, "modinfo: could not open %s: %s\n", + module = grab_elf_file(name); + if (!module) + error("modinfo: could not open %s: %s\n", name, strerror(errno)); - return NULL; - } + return module; } - if (kernel) { - if (strlen(basedir)) - asprintf(&moddir, "%s/%s/%s", - basedir, MODULE_DIR, kernel); - else - asprintf(&moddir, "%s/%s", - MODULE_DIR, kernel); - } else { + if (!kernel) { uname(&buf); - if (strlen(basedir)) - asprintf(&moddir, "%s/%s/%s", - basedir, MODULE_DIR, buf.release); - else - asprintf(&moddir, "%s/%s", - MODULE_DIR, buf.release); + kernel = buf.release; } - asprintf(&depname, "%s/%s", moddir, "modules.dep"); + if (strlen(basedir)) + nofail_asprintf(&moddir, "%s/%s/%s", basedir, MODULE_DIR, kernel); + else + nofail_asprintf(&moddir, "%s/%s", MODULE_DIR, kernel); /* Search for it in modules.dep. */ - data = grab_file(depname, size); + nofail_asprintf(&depname, "%s/%s", moddir, "modules.dep"); + data = grab_file(depname, &size); if (!data) { - fprintf(stderr, "modinfo: could not open %s\n", depname); + error("modinfo: could not open %s\n", depname); free(depname); return NULL; } free(depname); - for (p = data; p < data + *size; p = next_line(p, data + *size)) { - if (name_matches(p, data + *size, name)) { + for (p = data; p < data + size; p = next_line(p, data + size)) { + if (name_matches(p, data + size, name)) { int namelen = strcspn(p, ":"); + const char *dir; + char *filename; + + if ('/' == p[0]) + dir = basedir; /* old style deps - abs. path */ + else + dir = moddir; /* new style - relative path */ - if ('/' == p[0]) { /* old style deps - absolute path */ - *filename = malloc(namelen + strlen(basedir)+2); - if (strlen(basedir)) { - sprintf(*filename, "%s/", basedir); - memcpy(*filename+strlen(basedir)+1,p, - namelen); - (*filename)[namelen - +strlen(basedir)+1] = '\0'; - } else { - memcpy(*filename,p,namelen); - (*filename)[namelen] = '\0'; - } + if (strlen(dir)) { + nofail_asprintf(&filename, "%s/%s", dir, p); + filename[namelen + strlen(dir) + 1] = '\0'; } else { - *filename = malloc(namelen + strlen(moddir)+2); - sprintf(*filename, "%s/", moddir); - memcpy(*filename+strlen(moddir)+1, p,namelen); - (*filename)[namelen+strlen(moddir)+1] ='\0'; + filename = strndup(p, namelen); } - release_file(data, *size); - data = grab_file(*filename, size); - if (!data) - fprintf(stderr, - "modinfo: could not open %s: %s\n", + release_file(data, size); + module = grab_elf_file(filename); + if (!module) + error("modinfo: could not open %s: %s\n", *filename, strerror(errno)); - return data; + free(filename); + return module; } } - release_file(data, *size); - fprintf(stderr, "modinfo: could not find module %s\n", name); + release_file(data, size); + error("modinfo: could not find module %s\n", name); return NULL; } @@ -276,10 +263,11 @@ int main(int argc, char *argv[]) const char *field = NULL; const char *kernel = NULL; char sep = '\n'; - unsigned long infosize = 0; int opt, ret = 0; char *basedir = ""; + logging = 0; /* send messages to stderr */ + if (native_endianness() == 0) abort(); @@ -306,29 +294,25 @@ int main(int argc, char *argv[]) } for (opt = optind; opt < argc; opt++) { - void *info, *mod; - unsigned long modulesize; - char *filename; + void *info; + unsigned long infosize = 0; + struct elf_file *mod; - mod = grab_module(argv[opt], &modulesize, &filename, - kernel, basedir); + mod = grab_module(argv[opt], kernel, basedir); if (!mod) { ret = 1; continue; } - - info = get_section(mod, modulesize, ".modinfo", &infosize); + info = mod->ops->get_modinfo(mod, &infosize); if (!info) { - release_file(mod, modulesize); - free(filename); + release_elf_file(mod); continue; } if (field) - print_tag(field, info, infosize, filename, sep); + print_tag(field, info, infosize, mod->pathname, sep); else - print_all(info, infosize, filename, sep); - release_file(mod, modulesize); - free(filename); + print_all(info, infosize, mod->pathname, sep); + release_elf_file(mod); } return ret; } @@ -283,7 +283,7 @@ static const char *remove_moderror(int err) } } -static void replace_modname(struct module *module, +static void replace_modname(struct elf_file *module, void *mem, unsigned long len, const char *oldname, const char *newname) { @@ -301,86 +301,40 @@ static void replace_modname(struct module *module, } } - warn("Could not find old name in %s to replace!\n", module->filename); + warn("Could not find old name in %s to replace!\n", module->pathname); } -static void rename_module(struct module *module, - void *mod, - unsigned long len, +static void rename_module(struct elf_file *module, + const char *oldname, const char *newname) { void *modstruct; - unsigned long modstruct_len; + unsigned long len; /* Old-style */ - modstruct = get_section(mod, len, ".gnu.linkonce.this_module", - &modstruct_len); + modstruct = module->ops->load_section(module, + ".gnu.linkonce.this_module", &len); /* New-style */ if (!modstruct) - modstruct = get_section(mod, len, "__module", &modstruct_len); + modstruct = module->ops->load_section(module, "__module", &len); if (!modstruct) warn("Could not find module name to change in %s\n", - module->filename); + module->pathname); else - replace_modname(module, modstruct, modstruct_len, - module->modname, newname); -} - -/* Kernel told to ignore these sections if SHF_ALLOC not set. */ -static void invalidate_section32(void *mod, const char *secname) -{ - 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(void *mod, const char *secname) -{ - 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; + replace_modname(module, modstruct, len, oldname, newname); } -static void strip_section(struct module *module, - void *mod, - unsigned long len, - const char *secname) -{ - switch (elf_ident(mod, len, NULL)) { - case ELFCLASS32: - invalidate_section32(mod, secname); - break; - case ELFCLASS64: - invalidate_section64(mod, secname); - break; - default: - warn("Unknown module format in %s: not forcing version\n", - module->filename); - } -} - -static void clear_magic(struct module *module, void *mod, unsigned long len) +static void clear_magic(struct elf_file *module) { const char *p; - unsigned long modlen; + unsigned long len; /* Old-style: __vermagic section */ - strip_section(module, mod, len, "__vermagic"); + module->ops->strip_section(module, "__vermagic"); /* New-style: in .modinfo section */ - for (p = get_section(mod, len, ".modinfo", &modlen); - p; - p = next_string(p, &modlen)) { + p = module->ops->get_modinfo(module, &len); + for (; p; p = next_string(p, &len)) { if (strstarts(p, "vermagic=")) { memset((char *)p, 0, strlen(p)); return; @@ -667,8 +621,7 @@ static int insmod(struct list_head *list, const char *cmdline_opts) { int ret, fd; - unsigned long len; - void *map; + struct elf_file *module; const char *command; struct module *mod = list_entry(list->next, struct module, list); int rc = 0; @@ -712,21 +665,33 @@ static int insmod(struct list_head *list, goto out_optstring; } - map = grab_fd(fd, &len); - if (!map) { + module = grab_elf_file_fd(mod->filename, fd); + if (!module) { + /* This is an ugly hack that maintains the logic where + * init_module() sets errno = ENOEXEC if the file is + * not an ELF object. + */ + if (errno == ENOEXEC) { + struct stat st; + optstring = add_extra_options(mod->modname, + optstring, options); + if (dry_run) + goto out; + fstat(fd, &st); + ret = init_module(NULL, st.st_size, optstring); + goto out_hack; + } + error("Could not read '%s': %s\n", mod->filename, strerror(errno)); goto out_unlock; } - - /* Rename it? */ if (newname) - rename_module(mod, map, len, newname); - + rename_module(module, mod->modname, newname); if (strip_modversion) - strip_section(mod, map, len, "__versions"); + module->ops->strip_section(module, "__versions"); if (strip_vermagic) - clear_magic(mod, map, len); + clear_magic(module); /* Config file might have given more options */ optstring = add_extra_options(mod->modname, optstring, options); @@ -736,7 +701,8 @@ static int insmod(struct list_head *list, if (dry_run) goto out; - ret = init_module(map, len, optstring); + ret = init_module(module->data, module->len, optstring); +out_hack: if (ret != 0) { if (errno == EEXIST) { if (first_time) @@ -753,7 +719,7 @@ static int insmod(struct list_head *list, rc = 1; } out: - release_file(map, len); + release_elf_file(module); out_unlock: close_file(fd); out_optstring: @@ -826,67 +792,19 @@ 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) { - unsigned long size, secsize; - void *file = grab_file(filename, &size); - struct modver32_info *info32; - struct modver64_info *info64; - int n; - int conv; - - if (!file) { - error("%s: %s\n", filename, strerror(errno)); - return; - } - switch (elf_ident(file, size, &conv)) { - case ELFCLASS32: - info32 = get_section32(file, size, "__versions", &secsize, conv); - if (!info32) - return; /* Does not seem to be a kernel module */ - 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 = get_section64(file, size, "__versions", &secsize, conv); - if (!info64) - return; /* Does not seem to be a kernel module */ - 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); - } -} + struct elf_file *module; + module = grab_elf_file(filename); + if (!module) { + error("%s: %s\n", filename, strerror(errno)); + return; + } + 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) @@ -51,7 +51,7 @@ void output_pci_table(struct module *modules, FILE *out, char *dirname) make_shortname(shortname, i->pathname); for (e = t->pci_table; e->vendor; e = (void *)e + t->pci_size) - output_pci_entry(e, shortname, out, i->file.conv); + output_pci_entry(e, shortname, out, i->file->conv); } } @@ -102,7 +102,7 @@ void output_usb_table(struct module *modules, FILE *out, char *dirname) for (e = t->usb_table; e->idVendor || e->bDeviceClass || e->bInterfaceClass; e = (void *)e + t->usb_size) - output_usb_entry(e, shortname, out, i->file.conv); + output_usb_entry(e, shortname, out, i->file->conv); } } @@ -136,7 +136,7 @@ void output_ieee1394_table(struct module *modules, FILE *out, char *dirname) make_shortname(shortname, i->pathname); for (fw = t->ieee1394_table; fw->match_flags; fw = (void *) fw + t->ieee1394_size) - output_ieee1394_entry(fw, shortname, out, i->file.conv); + output_ieee1394_entry(fw, shortname, out, i->file->conv); } } @@ -170,7 +170,7 @@ void output_ccw_table(struct module *modules, FILE *out, char *dirname) for (e = t->ccw_table; e->cu_type || e->cu_model || e->dev_type || e->dev_model; e = (void *) e + t->ccw_size) - output_ccw_entry(e, shortname, out, i->file.conv); + output_ccw_entry(e, shortname, out, i->file->conv); } } @@ -425,6 +425,7 @@ void output_input_table(struct module *modules, FILE *out, char *dirname) char shortname[strlen(i->pathname) + 1]; int done = 0; struct module_tables *t = &i->tables; + int conv = i->file->conv; if (!t->input_table) continue; @@ -449,22 +450,20 @@ void output_input_table(struct module *modules, FILE *out, char *dirname) case sizeof(struct input_device_id_old_64): done = output_input_entry_64_old(p, shortname, - out, - i->file.conv); + out, conv); break; case sizeof(struct input_device_id_64): done = output_input_entry_64(p, shortname, - out, i->file.conv); + out, conv); break; case sizeof(struct input_device_id_old_32): done = output_input_entry_32_old(p, shortname, - out, - i->file.conv); + out, conv); break; case sizeof(struct input_device_id_32): done = output_input_entry_32(p, shortname, - out, i->file.conv); + out, conv); break; } } |