This introduces constructor and destructor for struct elf_file, following the grab/release naming pattern used elsewhere. Care is taken to ensure the constructor returns a valid errno on failure. The first user is grab_module() in depmod.c Signed-off-by: Andreas Robinson <andr345@xxxxxxxxx> --- depmod.c | 42 +++++------------------------ depmod.h | 2 +- elfops.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ elfops.h | 6 ++++ tables.c | 19 ++++++------- 5 files changed, 111 insertions(+), 45 deletions(-) diff --git a/depmod.c b/depmod.c index a7bd948..e636659 100644 --- a/depmod.c +++ b/depmod.c @@ -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. */ diff --git a/depmod.h b/depmod.h index be06b7c..d6d61f6 100644 --- a/depmod.h +++ b/depmod.h @@ -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]; diff --git a/elfops.c b/elfops.c index 9ae77ef..ac33c96 100644 --- a/elfops.c +++ b/elfops.c @@ -5,11 +5,15 @@ #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"; @@ -55,3 +59,86 @@ void *get_section(void *file, unsigned long filesize, return NULL; } } + +/* + * 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) +{ + struct elf_file *file; + + 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: + file->ops = &mod_ops32; + break; + case ELFCLASS64: + 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; +} + diff --git a/elfops.h b/elfops.h index 24ebc07..dffd9f5 100644 --- a/elfops.h +++ b/elfops.h @@ -16,6 +16,8 @@ struct kernel_symbol64 { struct elf_file { + char *pathname; + /* File operations */ struct module_ops *ops; @@ -75,4 +77,8 @@ void *get_section32(void *file, unsigned long filesize, 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/tables.c b/tables.c index ecbf030..2f44450 100644 --- a/tables.c +++ b/tables.c @@ -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; } } -- 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