Index: uspace/lib/c/generic/rtld/module.c
===================================================================
--- uspace/lib/c/generic/rtld/module.c	(revision 0f792c28c69f695fd1956a86e0489bd2ea27cc3f)
+++ uspace/lib/c/generic/rtld/module.c	(revision b66cc977e145eaa74a7e9fe52a4a2e995c81ad02)
@@ -91,5 +91,5 @@
  * path components are ignored.
  */
-module_t *module_find(const char *name)
+module_t *module_find(rtld_t *rtld, const char *name)
 {
 	const char *p, *soname;
@@ -106,5 +106,5 @@
 
 	/* Traverse list of all modules. Not extremely fast, but simple */
-	list_foreach(runtime_env->modules, modules_link, module_t, m) {
+	list_foreach(rtld->modules, modules_link, module_t, m) {
 		DPRINTF("m = %p\n", m);
 		if (str_cmp(m->dyn.soname, soname) == 0) {
@@ -122,7 +122,7 @@
  * Currently this trivially tries to load '/<name>'.
  */
-module_t *module_load(const char *name)
-{
-	elf_info_t info;
+module_t *module_load(rtld_t *rtld, const char *name)
+{
+	elf_finfo_t info;
 	char name_buf[NAME_BUF_SIZE];
 	module_t *m;
@@ -135,4 +135,6 @@
 	}
 
+	m->rtld = rtld;
+
 	if (str_size(name) > NAME_BUF_SIZE - 2) {
 		printf("soname too long. increase NAME_BUF_SIZE\n");
@@ -145,6 +147,6 @@
 
 	/* FIXME: need to real allocation of address space */
-	m->bias = runtime_env->next_bias;
-	runtime_env->next_bias += 0x100000;
+	m->bias = rtld->next_bias;
+	rtld->next_bias += 0x100000;
 
 	DPRINTF("filename:'%s'\n", name_buf);
@@ -171,5 +173,5 @@
 
 	/* Insert into the list of loaded modules */
-	list_append(&m->modules_link, &runtime_env->modules);
+	list_append(&m->modules_link, &rtld->modules);
 
 	return m;
@@ -221,7 +223,7 @@
 
 			DPRINTF("%s needs %s\n", m->dyn.soname, dep_name);
-			dm = module_find(dep_name);
+			dm = module_find(m->rtld, dep_name);
 			if (!dm) {
-				dm = module_load(dep_name);
+				dm = module_load(m->rtld, dep_name);
 				module_load_deps(dm);
 			}
@@ -241,9 +243,9 @@
  * @param	start	The module where to start from.
  */
-void modules_process_relocs(module_t *start)
-{
-	list_foreach(runtime_env->modules, modules_link, module_t, m) {
-		/* Skip rtld, since it has already been processed */
-		if (m != &runtime_env->rtld) {
+void modules_process_relocs(rtld_t *rtld, module_t *start)
+{
+	list_foreach(rtld->modules, modules_link, module_t, m) {
+		/* Skip rtld module, since it has already been processed */
+		if (m != &rtld->rtld) {
 			module_process_relocs(m);
 		}
@@ -253,7 +255,7 @@
 /** Clear BFS tags of all modules.
  */
-void modules_untag(void)
-{
-	list_foreach(runtime_env->modules, modules_link, module_t, m) {
+void modules_untag(rtld_t *rtld)
+{
+	list_foreach(rtld->modules, modules_link, module_t, m) {
 		m->bfs_tag = false;
 	}
Index: uspace/lib/c/generic/rtld/rtld.c
===================================================================
--- uspace/lib/c/generic/rtld/rtld.c	(revision 0f792c28c69f695fd1956a86e0489bd2ea27cc3f)
+++ uspace/lib/c/generic/rtld/rtld.c	(revision b66cc977e145eaa74a7e9fe52a4a2e995c81ad02)
@@ -35,10 +35,15 @@
  */
 
+#include <errno.h>
+#include <rtld/module.h>
 #include <rtld/rtld.h>
+#include <rtld/rtld_debug.h>
+#include <stdlib.h>
 
-runtime_env_t *runtime_env;
-static runtime_env_t rt_env_static;
+rtld_t *runtime_env;
+static rtld_t rt_env_static;
+static module_t prog_mod;
 
-/** Initialize the loder for use in a statically-linked binary. */
+/** Initialize the runtime linker for use in a statically-linked executable. */
 void rtld_init_static(void)
 {
@@ -49,4 +54,60 @@
 }
 
+/** Initialize and process a dynamically linked executable.
+ *
+ * @param p_info Program info
+ * @return EOK on success or non-zero error code
+ */
+int rtld_prog_process(elf_finfo_t *p_info, rtld_t **rre)
+{
+	rtld_t *env;
+
+	DPRINTF("Load dynamically linked program.\n");
+
+	/* Allocate new RTLD environment to pass to the loaded program */
+	env = calloc(1, sizeof(rtld_t));
+	if (env == NULL)
+		return ENOMEM;
+
+	/*
+	 * First we need to process dynamic sections of the executable
+	 * program and insert it into the module graph.
+	 */
+
+	DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
+	dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
+	prog_mod.bias = 0;
+	prog_mod.dyn.soname = "[program]";
+	prog_mod.rtld = env;
+
+	/* Initialize list of loaded modules */
+	list_initialize(&env->modules);
+	list_append(&prog_mod.modules_link, &env->modules);
+
+	/* Pointer to program module. Used as root of the module graph. */
+	env->program = &prog_mod;
+
+	/* Work around non-existent memory space allocation. */
+	env->next_bias = 0x1000000;
+
+	/*
+	 * Now we can continue with loading all other modules.
+	 */
+
+	DPRINTF("Load all program dependencies\n");
+	module_load_deps(&prog_mod);
+
+	/*
+	 * Now relocate/link all modules together.
+	 */
+
+	/* Process relocations in all modules */
+	DPRINTF("Relocate all modules\n");
+	modules_process_relocs(env, &prog_mod);
+
+	*rre = env;
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/rtld/symbol.c
===================================================================
--- uspace/lib/c/generic/rtld/symbol.c	(revision 0f792c28c69f695fd1956a86e0489bd2ea27cc3f)
+++ uspace/lib/c/generic/rtld/symbol.c	(revision b66cc977e145eaa74a7e9fe52a4a2e995c81ad02)
@@ -39,4 +39,5 @@
 
 #include <elf/elf.h>
+#include <rtld/module.h>
 #include <rtld/rtld.h>
 #include <rtld/rtld_debug.h>
@@ -132,5 +133,5 @@
 
 	/* Mark all vertices (modules) as unvisited */	
-	modules_untag();
+	modules_untag(start->rtld);
 
 	/* Insert root (the program) into the queue and tag it */
@@ -219,7 +220,7 @@
 	/* Not DT_SYMBOLIC or no match. Now try other locations. */
 
-	if (runtime_env->program) {
+	if (origin->rtld->program) {
 		/* Program is dynamic -- start with program as root. */
-		return symbol_bfs_find(name, runtime_env->program, flags, mod);
+		return symbol_bfs_find(name, origin->rtld->program, flags, mod);
 	} else {
 		/* Program is static -- start with @a origin as root. */
