[PATCH 05/16] elfops, depmod: add elf_file grab/release functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux