Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision b678410d7e2eada8e2e3f65aaf7c4efc831777d6)
+++ uspace/srv/loader/Makefile	(revision b40a3b6ab970c25922e0c465b01ed964c92cac85)
@@ -41,5 +41,5 @@
 EXTRA_CLEAN = $(LINKER_SCRIPT)
 
-EXTRA_CFLAGS = -Iinclude
+EXTRA_CFLAGS = -Iinclude -I../../lib/c/rtld/include
 
 BINARY = loader
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision b678410d7e2eada8e2e3f65aaf7c4efc831777d6)
+++ uspace/srv/loader/main.c	(revision b40a3b6ab970c25922e0c465b01ed964c92cac85)
@@ -63,7 +63,14 @@
 #include <elf_load.h>
 
+/* From librtld */
+#include <rtld.h>
+#include <dynamic.h>
+#include <elf_load.h>
+#include <module.h>
+
 #define DPRINTF(...)
 
 void program_run(void *entry, pcb_t *pcb);
+static int ldr_load_dyn_linked(elf_info_t *p_info);
 
 /** Pathname of the file that will be loaded */
@@ -91,10 +98,11 @@
 
 static elf_info_t prog_info;
-static elf_info_t interp_info;
-
-static bool is_dyn_linked;
 
 /** Used to limit number of connections to one. */
 static bool connected = false;
+
+/** State structure of the dynamic linker. */
+runtime_env_t dload_re;
+static module_t prog_mod;
 
 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
@@ -304,29 +312,64 @@
 	if (prog_info.interp == NULL) {
 		/* Statically linked program */
-		is_dyn_linked = false;
 		async_answer_0(rid, EOK);
 		return 0;
 	}
 	
-	printf("Load ELF interpreter '%s'\n", prog_info.interp);
-	rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
-	if (rc != EE_OK) {
-		DPRINTF("Failed to load interpreter '%s.'\n",
-		    prog_info.interp);
-		async_answer_0(rid, EINVAL);
-		return 1;
-	}
-	
-	printf("Run interpreter.\n");
-	printf("entry point: 0x%lx\n", (unsigned long) interp_info.entry);
-	printf("pcb address: 0x%lx\n", (unsigned long) &pcb);
-	printf("prog dynamic: 0x%lx\n", (unsigned long) prog_info.dynamic);
-
-	is_dyn_linked = true;
-	async_answer_0(rid, EOK);
-	
+	DPRINTF("Binary is dynamically linked.\n");
+	DPRINTF(" - pcb address: %p\n", &pcb);
+	DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
+
+	rc = ldr_load_dyn_linked(&prog_info);
+
+	async_answer_0(rid, rc);
 	return 0;
 }
 
+static int ldr_load_dyn_linked(elf_info_t *p_info)
+{
+	runtime_env = &dload_re;
+
+	DPRINTF("Load dynamically linked program.\n");
+
+	/*
+	 * 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]";
+
+	/* Initialize list of loaded modules */
+	list_initialize(&runtime_env->modules_head);
+	list_append(&prog_mod.modules_link, &runtime_env->modules_head);
+
+	/* Pointer to program module. Used as root of the module graph. */
+	runtime_env->program = &prog_mod;
+
+	/* Work around non-existent memory space allocation. */
+	runtime_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(&prog_mod);
+
+	/* Pass runtime evironment pointer through PCB. */
+	pcb.rtld_runtime = (void *) runtime_env;
+
+	return 0;
+}
 
 /** Run the previously loaded program.
@@ -340,4 +383,6 @@
 	const char *cp;
 	
+	DPRINTF("Set task name\n");
+
 	/* Set the task name. */
 	cp = str_rchr(pathname, '/');
@@ -345,16 +390,9 @@
 	task_set_name(cp);
 	
-	if (is_dyn_linked == true) {
-		/* Dynamically linked program */
-		DPRINTF("Run ELF interpreter.\n");
-		DPRINTF("Entry point: %p\n", interp_info.entry);
-		
-		async_answer_0(rid, EOK);
-		program_run(interp_info.entry, &pcb);
-	} else {
-		/* Statically linked program */
-		async_answer_0(rid, EOK);
-		program_run(prog_info.entry, &pcb);
-	}
+	/* Run program */
+	DPRINTF("Reply OK\n");
+	async_answer_0(rid, EOK);
+	DPRINTF("Jump to entry point at %p\n", pcb.entry);
+	program_run(prog_info.entry, &pcb);
 	
 	/* Not reached */
