[syslinux:elflink] ldlinux: Use DT_NEEDED for module dependencies

syslinux-bot for Matt Fleming matt.fleming at linux.intel.com
Tue Jul 12 20:03:20 PDT 2011


Commit-ID:  558de6072a2fae89a27d10119b3ea49a4741db16
Gitweb:     http://syslinux.zytor.com/commit/558de6072a2fae89a27d10119b3ea49a4741db16
Author:     Matt Fleming <matt.fleming at linux.intel.com>
AuthorDate: Mon, 6 Jun 2011 14:12:45 +0100
Committer:  Matt Fleming <matt.fleming at linux.intel.com>
CommitDate: Tue, 7 Jun 2011 15:59:58 +0100

ldlinux: Use DT_NEEDED for module dependencies

The ELF file format uses DT_NEEDED entries in the dynamic section to
name any shared library dependencies. Instead of rolling our own
dependency logic via the modules.dep file and elf_gen_dep.sh script
use the DT_NEEDED entries.

Signed-off-by: Matt Fleming <matt.fleming at linux.intel.com>


---
 .gitignore                        |    1 -
 com32/elflink/ldlinux/execute.c   |    2 -
 com32/include/sys/exec.h          |   12 ---
 com32/lib/sys/module/elf_module.c |   51 +++++++++++++-
 com32/lib/sys/module/exec.c       |  144 -------------------------------------
 core/elflink/load_env32.c         |    1 -
 elf_gen_dep.sh                    |  130 ---------------------------------
 7 files changed, 50 insertions(+), 291 deletions(-)

diff --git a/.gitignore b/.gitignore
index 05f0d14..98ea19f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,4 +50,3 @@
 *GPATH
 *GRTAGS
 *GTAGS
-modules.dep
diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c
index 635e327..dff59e6 100644
--- a/com32/elflink/ldlinux/execute.c
+++ b/com32/elflink/ldlinux/execute.c
@@ -132,7 +132,6 @@ void execute(const char *cmdline, enum kernel_type type)
 		}
 
 		argv[argc] = NULL;
-		module_load_dependencies(kernel, "modules.dep");
 		spawn_load(kernel, argc, argv);
 	} else if (type == KT_KERNEL) {
 		/* Need add one item for kernel load, as we don't use
@@ -141,7 +140,6 @@ void execute(const char *cmdline, enum kernel_type type)
 	} else if (type == KT_CONFIG) {
 		/* kernel contains the config file name */
 		char *spawn_load_param[2] = { args, NULL };
-		module_load_dependencies("ui.c32", "modules.dep");
 		spawn_load(kernel, 1, spawn_load_param);
 	} else {
 		/* process the image need int 22 support */
diff --git a/com32/include/sys/exec.h b/com32/include/sys/exec.h
index 656f8e2..9c00e4a 100644
--- a/com32/include/sys/exec.h
+++ b/com32/include/sys/exec.h
@@ -20,16 +20,6 @@
 #define EXEC_ROOT_NAME			"_root_.c32"
 
 /**
- * MODULES_DEP - The name of the standard module dependency file
- *
- * This is the file which contains information about the module dependency
- * graph ( what other modules it depends on ). The file format is identical
- * to the standard linux modules.dep file... for more information check out the
- * man page ).
- */
-#define MODULES_DEP "modules.dep"
-
-/**
  * spawn_load - Load a library module or executes an executable one
  * @name	the name of the library/executable to use, including the extension
  * 			(e.g. 'sort.c32')
@@ -43,8 +33,6 @@
  */
 extern int spawn_load(const char *name, int argc, char **argv);
 
-extern int module_load_dependencies(const char*name,const char*dep_file);
-
 /**
  * exec_init - Initialize the dynamic execution environment.
  *
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index 8db4220..7d8dad4 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -18,6 +18,8 @@
 #include "elfutils.h"
 #include "common.h"
 
+#define MAX_NR_DEPS	64
+
 static int check_header(Elf32_Ehdr *elf_hdr) {
 	int res;
 
@@ -178,6 +180,8 @@ out:
 	return res;
 }
 
+static int nr_needed;
+static Elf32_Word needed[MAX_NR_DEPS];;
 
 static int prepare_dynlinking(struct elf_module *module) {
 	Elf32_Dyn  *dyn_entry = module->dyn_table;
@@ -185,7 +189,18 @@ static int prepare_dynlinking(struct elf_module *module) {
 	while (dyn_entry->d_tag != DT_NULL) {
 		switch (dyn_entry->d_tag) {
 		case DT_NEEDED:
-			// TODO: Manage dependencies here
+			/*
+			 * It's unlikely there'll be more than
+			 * MAX_NR_DEPS DT_NEEDED entries but if there
+			 * are then inform the user that we ran out of
+			 * space.
+			 */
+			if (nr_needed < MAX_NR_DEPS)
+				needed[nr_needed++] = dyn_entry->d_un.d_ptr;
+			else {
+				printf("Too many dependencies!\n");
+				return -1;
+			}
 			break;
 		case DT_HASH:
 			module->hash_table =
@@ -447,11 +462,45 @@ int module_load(struct elf_module *module) {
 	CHECKED(res, load_segments(module, &elf_hdr), error);
 	//printf("bleah... 3\n");
 	// Obtain dynamic linking information
+	nr_needed = 0;
 	CHECKED(res, prepare_dynlinking(module), error);
 	//printf("check... 4\n");
 	//
 	//dump_elf_module(module);
 
+	/* Find modules we need to load as dependencies */
+	if (module->str_table) {
+		int i, n;
+
+		/*
+		 * nr_needed can be modified by recursive calls to
+		 * module_load() so keep a local copy on the stack.
+		 */
+		n = nr_needed;
+		for (i = 0; i < n; i++) {
+			size_t len, j;
+			char *dep, *p;
+
+			dep = module->str_table + needed[i];
+
+			/* strip everything but the last component */
+			j = len = strlen(dep);
+			if (!len)
+				continue;
+
+			p = dep + len - 1;
+			while (j > 0 && *p && *p != '/') {
+				p--;
+				j--;
+			}
+
+			if (*p++ == '/') {
+				char argv[2] = { p, NULL };
+				spawn_load(p, 1, argv);
+			}
+		}
+	}
+
 	// Check the symbols for duplicates / missing definitions
 	CHECKED(res, check_symbols(module), error);
 	//printf("check... 5\n");
diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c
index 1ed3263..71d3192 100644
--- a/com32/lib/sys/module/exec.c
+++ b/com32/lib/sys/module/exec.c
@@ -346,150 +346,6 @@ int spawn_load(const char *name, int argc, char **argv)
 	*/
 }
 
-/*
- * Avoid circular dependencies.
- *
- * It's possible that someone messed up the modules.dep file and that
- * it includes circular dependencies, so we need to take steps here to
- * avoid looping in module_load_dependencies() forever.
- *
- * We build a singly-linked list of modules that are in the middle of
- * being loaded. When they have completed loading their entry is
- * removed from this list in LIFO order (new entries are always added
- * to the head of the list).
- */
-struct loading_dep {
-	const char *name;
-	struct module_dep *next;
-};
-static struct loading_dep *loading_deps;
-
-/*
- * Remember that because we insert elements in a LIFO order we need to
- * start from the end of the list and work towards the front so that
- * we print the modules in the order in which we tried to load them.
- *
- * Yay for recursive function calls.
- */
-static void print_loading_dep(struct loading_dep *dep)
-{
-	if (dep) {
-		print_loading_dep(dep->next);
-		printf("\t\t\"%s\"\n", dep->name);
-	}
-}
-
-int module_load_dependencies(const char *name,const char *dep_file)
-{
-	FILE *d_file=fopen(dep_file,"r");
-	char line[2048],aux[2048],temp_name[MODULE_NAME_SIZE],slbz[24];
-	int i=0,j=0,res=0;
-	struct loading_dep *dep;
-
-	if(d_file==NULL)
-	{
-		DBG_PRINT("Could not open object file '%s'\n",dep_file);
-		return -1;
-	}
-
-	/*
-	 * Are we already in the middle of loading this module's
-	 * dependencies?
-	 */
-	for (dep = loading_deps; dep; dep = dep->next) {
-		if (!strcasecmp(dep->name, name))
-			break;	/* found */
-	}
-
-	if (dep) {
-		struct loading_dep *last, *prev;
-
-		/* Dup! */
-		printf("\t\tCircular depedency detected when loading "
-		       "modules!\n");
-		printf("\t\tModules dependency chain looks like this,\n\n");
-		print_loading_dep(loading_deps);
-		printf("\n\t\t... and we tried to load \"%s\" again\n", name);
-
-		return -1;
-	} else {
-		dep = malloc(sizeof(*dep));
-		if (!dep) {
-			printf("Failed to alloc memory for loading_dep\n");
-			return -1;
-		}
-		
-		dep->name = name;
-		dep->next = loading_deps;
-
-		/* Insert at the head of the list */
-		loading_deps = dep;
-	}
-
-	/* Note from feng:
-	 * new modues.dep has line like this:
-	 *	a.c32: b.32 c.c32 d.c32
-	 * with desktop glibc
-	 *	sscanf(line,"%[^:]: %[^\n]", temp_name, aux);
-	 * works, which doesn't work here
-	 */
-	memset(temp_name, 0, sizeof(temp_name));
-	memset(aux, 0, sizeof(aux));
-	while (1) {
-		if(fgets(line,2048,d_file)==NULL)
-			break;
-
-		//sscanf(line,"%s %[^\t\n]s",temp_name,aux);
-		//sscanf(line,"%[^:]: %[^\n]", temp_name, aux);
-		//sscanf(line,"%[^:]: %[^\n]\n", temp_name, aux);
-
-		sscanf(line,"%[^:]:", temp_name);
-		if (!strncmp(name, temp_name, strlen(name))) {
-			/* The next 2 chars should be ':' and ' ' */
-			i = strlen(temp_name);
-			if (line[i] != ':' || line[i+1] != ' ')
-				break;
-
-			i +=2;
-			j = 0;
-			while (line[i] != '\n')
-				aux[j++] = line[i++];
-			aux[j] = '\0';
-			//dprintf("found dependency: temp_name = %s, aux = %s, name = %s", temp_name, aux, name);
-			break;
-		}
-	}
-	fclose(d_file);
-
-	/* Reuse temp_name for dependent module name buffer */
-	memset(temp_name, 0, sizeof(temp_name));
-	i = 0;
-	while (aux[i]) {
-		sscanf(aux + i, "%s", temp_name);
-		//dprintf("load module: %s", temp_name);
-		i += strlen(temp_name);
-		i++;	/* skip a space */
-
-		if (strlen(temp_name)) {
-			char *argv[2] = { temp_name, NULL };
-			int ret;
-
-			ret = module_load_dependencies(temp_name,
-						       MODULES_DEP);
-			if (!ret) {
-				if (spawn_load(temp_name, 1, argv) < 0)
-					continue;
-			}
-		}
-	}
-
-	/* Remove our entry from the head of loading_deps */
-	loading_deps = loading_deps->next;
-	free(dep);
-
-	return 0;
-}
-
 void exec_term(void)
 {
 	modules_term();
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index 793ecd5..e639653 100644
--- a/core/elflink/load_env32.c
+++ b/core/elflink/load_env32.c
@@ -75,6 +75,5 @@ void load_env32(com32sys_t * regs)
 
 	init_module_subsystem(&core_module);
 
-	module_load_dependencies(LDLINUX, "modules.dep");
 	spawn_load(LDLINUX, 1, argv);
 }
diff --git a/elf_gen_dep.sh b/elf_gen_dep.sh
deleted file mode 100755
index 1badb64..0000000
--- a/elf_gen_dep.sh
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/bin/sh
-
-#######################################################
-#  Round 1: get all the loacl and external symbols
-#######################################################
-
-for i in core/isolinux.elf core/pxelinux.elf com32/*/*.c32 com32/*/*/*.c32
-do
-	# module=$(echo $i | sed "s/^\(.*\).o$/\1/")
-	
-	# remove the path infomation
-	module=$(echo $i | sed "s/^.*\/\(.*\)$/\1/")
-
-	readelf -s $i > temp.txt
-	#Get the last 2 items of each line
-	cut -c47- temp.txt > $module.txt 
-	rm temp.txt
-
-	#Get the unresolved symbols
-	sed -n -e "/UND $/d" -e "/_GLOBAL_OFFSET_TABLE_/d" -e  "s/^.UND.\(.*\)$/\1/p" $module.txt > $module.ext
-
-	#Get the local symbols
-	sed -n -e "/UND/d" -e "/ABS/d" -e "/...[0-9] $/d" -e "/...[0-9] \./d" -e "/...[0-9]/p" $module.txt > $module.int 
-	sed -i -e "s/^.....//g" $module.int
-	sed -i -e "s/^\(.*\)$/\1 <$module>/g" $module.int
-	# Delete all whitespace
-	sed -i -e "s/^[ \t]*$//g" $module.int
-
-	cat $module.int >> all.txt
-done
-
-
-touch modules.dep
-
-#######################################################
-#  Round 2: get all the loacl and external symbols
-#######################################################
-
-# Consolidate the dependent modules to one line and remove
-# the redundant ones, and the "core" 
-rm_cr ()
-{
-	touch rmcr.tmp
-	all_dep=$module:
-	space=' '
-
-	while read line
-	do
-		# skip the module which is alreay on the list 
-		grep $line rmcr.tmp > /dev/null && continue
-
-		# grep extlinux/isolinux and remove them
-		echo $line | grep extlinux > /dev/null && continue
-		echo $line | grep isolinux > /dev/null && continue
-		echo $line | grep pxelinux > /dev/null && continue
-		echo $line | grep ldlinux > /dev/null && continue
-
-		all_dep=$all_dep$space$line
-		echo $all_dep > rmcr.tmp
-	done
-
-	echo $all_dep >> modules.dep
-	rm rmcr.tmp
-}
-
-# Find the symbol belongs to which module by screening all.txt, do it
-# one by one, and the result "resolve.tmp" will be a file like:
-#	a.c32
-#	b.c32
-#	c.c32
-resolve_sym ()
-{
-	touch resolve.tmp
-
-	while read symbol 
-	do
-		# If no one provides the symbol we're trying to
-		# resolve then add it to the list of unresolved
-		# symbols.
-		grep -q $symbol all.txt
-		if [ $? -ne 0 ]; then
-			# We only need to add the symbol once
-			if [[ ! "$unresolved_symbols" =~ "$symbol" ]]; then
-				unresolved_symbols="$unresolved_symbols $symbol"
-			fi
-		else
-			#echo $symbol
-			sed -n -e "s/^$symbol <\(.*\)>/\1/p" all.txt | head -n1 >> resolve.tmp
-			#grep $symbol all.txt
-		fi
-	done
-
-	rm_cr < resolve.tmp
-	rm resolve.tmp
-}
-
-#only test name start with a/b
-#rm [c-z]*.ext
-
-if [ -e modules.dep ]
-then
-	rm modules.dep
-	touch modules.dep
-fi
-
-# Don't need to resolve the core symbols
-for i in extlinux isolinux pxelinux
-do
-	if [ -e $i.elf.ext ]
-	then
-		rm $i.elf.ext
-	fi
-done
-
-for i in *.ext 
-do
-	module=$(echo $i | sed "s/^\(.*\).ext$/\1/")
-	resolve_sym < $i
-done
-
-# Do some cleanup
-rm *.txt
-rm *.ext
-rm *.int
-
-if [ "$unresolved_symbols" ]; then
-	echo "WARNING: These symbols could not be resolved:" $unresolved_symbols
-fi
-
-echo ELF modules dependency is bult up, pls check modules.dep!



More information about the Syslinux-commits mailing list