Index: .bzrignore
===================================================================
--- .bzrignore	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ .bzrignore	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -3,4 +3,7 @@
 *.prev
 *.ag.probe.[cs]
+*.lo
+*.la
+*.so.*
 Makefile.depend
 Makefile.common
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ boot/Makefile.common	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -158,6 +158,7 @@
 ifeq ($(CONFIG_BUILD_SHARED_LIBS), y)
 	RD_LIBS += \
-		$(USPACE_PATH)/lib/c/libc.so0 \
-		$(USPACE_PATH)/lib/softint/libsofti.so0
+		$(USPACE_PATH)/lib/c/libc.so.0 \
+		$(USPACE_PATH)/lib/softint/libsoftint.so.0 \
+		$(USPACE_PATH)/lib/math/libmath.so.0
 	RD_APPS += \
 		$(USPACE_PATH)/app/dltest/dltest
Index: kernel/arch/ia32/include/arch/barrier.h
===================================================================
--- kernel/arch/ia32/include/arch/barrier.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ kernel/arch/ia32/include/arch/barrier.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -54,5 +54,5 @@
 NO_TRACE static inline void cpuid_serialization(void)
 {
-#ifndef __IN_SHARED_LIBC__
+#ifndef __PIC__
 	asm volatile (
 		"xorl %%eax, %%eax\n"
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/Makefile.common	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -203,9 +203,9 @@
 	endif
 else
-	BASE_LIBS = $(LIBC_PREFIX)/libc.so0 $(LIBSOFTINT_PREFIX)/libsofti.so0
+	BASE_LIBS = $(LIBC_PREFIX)/libc.so.0 $(LIBSOFTINT_PREFIX)/libsoftint.so.0
 	LFLAGS += -Bdynamic
 	LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld
 	ifeq ($(MATH),y)
-		BASE_LIBS += $(LIBMATH_PREFIX)/libmath.so0
+		BASE_LIBS += $(LIBMATH_PREFIX)/libmath.so.0
 	endif
 endif
@@ -270,5 +270,5 @@
 	-integrated-as -pipe -g -target $(CLANG_TARGET) -D__$(ENDIANESS)__
 
-LIB_CFLAGS = $(CFLAGS) -fPIC -D__IN_SHARED_LIBC__
+LIB_CFLAGS = $(CFLAGS) -fPIC
 LIB_LFLAGS = $(LFLAGS) -shared -soname $(LSONAME) --whole-archive
 
Index: uspace/app/corecfg/corecfg.c
===================================================================
--- uspace/app/corecfg/corecfg.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/app/corecfg/corecfg.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -37,5 +37,5 @@
 #include <stdio.h>
 
-#define NAME "dnscfg"
+#define NAME "corecfg"
 
 static void print_syntax(void)
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -45,5 +45,5 @@
 LIBRARY = libc
 SLIBRARY = libc.so.0.0
-LSONAME = libc.so0
+LSONAME = libc.so.0
 
 LIBS = $(LIBURCU_PREFIX)/liburcu.a
@@ -79,4 +79,5 @@
 	generic/dlfcn.c \
 	generic/elf/elf_load.c \
+	generic/elf/elf_mod.c \
 	generic/event.c \
 	generic/errno.c \
Index: uspace/lib/c/arch/ia32/src/rtld/reloc.c
===================================================================
--- uspace/lib/c/arch/ia32/src/rtld/reloc.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/arch/ia32/src/rtld/reloc.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -69,5 +69,5 @@
 	uint32_t sym_size;
 	char *str_tab;
-	
+
 	elf_symbol_t *sym_def;
 	module_t *dest;
@@ -80,5 +80,5 @@
 
 	DPRINTF("address: 0x%x, entries: %d\n", (uintptr_t)rt, rt_entries);
-	
+
 	for (i = 0; i < rt_entries; ++i) {
 //		DPRINTF("symbol %d: ", i);
@@ -100,5 +100,5 @@
 //			DPRINTF("rel_type: %x, rel_offset: 0x%x\n", rel_type, r_offset);
 			sym_def = symbol_def_find(str_tab + sym->st_name,
-			    m, &dest);
+			    m, ssf_none, &dest);
 //			DPRINTF("dest name: '%s'\n", dest->dyn.soname);
 //			DPRINTF("dest bias: 0x%x\n", dest->bias);
@@ -137,7 +137,22 @@
 			/*
 			 * Copy symbol data from shared object to specified
-			 * location.
+			 * location. Need to find the 'source', i.e. the
+			 * other instance of the object than the one in the
+			 * executable program.
 			 */
 			DPRINTF("fixup R_386_COPY (s)\n");
+
+			sym_def = symbol_def_find(str_tab + sym->st_name,
+			    m, ssf_noroot, &dest);
+
+			if (sym_def) {
+				sym_addr = (uint32_t)
+				    symbol_get_addr(sym_def, dest);
+			} else {
+				printf("Source definition of '%s' not found.\n",
+				    str_tab + sym->st_name);
+				continue;
+			}
+
 			sym_size = sym->st_size;
 			if (sym_size != sym_def->st_size) {
@@ -147,7 +162,8 @@
 					sym_size = sym_def->st_size;
 			}
+
 			memcpy(r_ptr, (const void *)sym_addr, sym_size);
 			break;
-			
+
 		case R_386_RELATIVE:
 			DPRINTF("fixup R_386_RELATIVE (b+a)\n");
Index: uspace/lib/c/generic/dlfcn.c
===================================================================
--- uspace/lib/c/generic/dlfcn.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/generic/dlfcn.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -42,4 +42,5 @@
 
 #include <rtld/module.h>
+#include <rtld/rtld.h>
 #include <rtld/symbol.h>
 
@@ -56,8 +57,8 @@
 
 	printf("module_find('%s')\n", path);
-	m = module_find(path);
+	m = module_find(runtime_env, path);
 	if (m == NULL) {
 		printf("NULL. module_load('%s')\n", path);
-		m = module_load(path);
+		m = module_load(runtime_env, path);
 		printf("module_load_deps(m)\n");
 		module_load_deps(m);
@@ -81,5 +82,5 @@
 
 	printf("dlsym(0x%lx, \"%s\")\n", (long)mod, sym_name);
-	sd = symbol_bfs_find(sym_name, (module_t *) mod, &sm);
+	sd = symbol_bfs_find(sym_name, (module_t *) mod, ssf_none, &sm);
 	if (sd != NULL) {
 		return symbol_get_addr(sd, sm);
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -1,6 +1,4 @@
 /*
- * Copyright (c) 2006 Sergey Bondari
- * Copyright (c) 2006 Jakub Jermar
- * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2016 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,84 +34,57 @@
  * @file
  * @brief	Userspace ELF loader.
- *
- * This module allows loading ELF binaries (both executables and
- * shared objects) from VFS. The current implementation allocates
- * anonymous memory, fills it with segment data and then adjusts
- * the memory areas' flags to the final value. In the future,
- * the segments will be mapped directly from the file.
  */
 
+#include <elf/elf_load.h>
+#include <elf/elf_mod.h>
+#include <errno.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <align.h>
-#include <assert.h>
-#include <as.h>
-#include <elf/elf.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <smc.h>
-#include <loader/pcb.h>
-#include <entry_point.h>
+#include <stdlib.h>
 
-#include <elf/elf_load.h>
+#ifdef CONFIG_RTLD
+#include <rtld/rtld.h>
+#endif
 
 #define DPRINTF(...)
 
-static const char *error_codes[] = {
-	"no error",
-	"invalid image",
-	"address space error",
-	"incompatible image",
-	"unsupported image type",
-	"irrecoverable error"
-};
-
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
-static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
-
-/** Load ELF binary from a file.
+/** Load ELF program.
  *
- * Load an ELF binary from the specified file. If the file is
- * an executable program, it is loaded unbiased. If it is a shared
- * object, it is loaded with the bias @a so_bias. Some information
- * extracted from the binary is stored in a elf_info_t structure
- * pointed to by @a info.
- *
- * @param file_name Path to the ELF file.
- * @param so_bias   Bias to use if the file is a shared object.
- * @param info      Pointer to a structure for storing information
- *                  extracted from the binary.
- *
- * @return EOK on success or negative error code.
- *
+ * @param file_name File name
+ * @param info Place to store ELF program information
+ * @return EOK on success or non-zero error code
  */
-int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
-    elf_info_t *info)
+int elf_load(const char *file_name, elf_info_t *info)
 {
-	elf_ld_t elf;
-
-	int fd;
+#ifdef CONFIG_RTLD
+	rtld_t *env;
+#endif
 	int rc;
 
-	fd = open(file_name, O_RDONLY);
-	if (fd < 0) {
-		DPRINTF("failed opening file\n");
-		return -1;
+	rc = elf_load_file(file_name, 0, 0, &info->finfo);
+	if (rc != EE_OK) {
+		DPRINTF("Failed to load executable '%s'.\n", file_name);
+		return rc;
 	}
 
-	elf.fd = fd;
-	elf.info = info;
-	elf.flags = flags;
+	if (info->finfo.interp == NULL) {
+		/* Statically linked program */
+		DPRINTF("Binary is statically linked.\n");
+		info->env = NULL;
+		return EE_OK;
+	}
 
-	rc = elf_load(&elf, so_bias);
+	DPRINTF("Binary is dynamically linked.\n");
+#ifdef CONFIG_RTLD
+	DPRINTF( "- prog dynamic: %p\n", info->finfo.dynamic);
 
-	close(fd);
-
+	rc = rtld_prog_process(&info->finfo, &env);
+	info->env = env;
+#else
+	rc = EE_UNSUPPORTED;
+#endif
 	return rc;
 }
 
-/** Create the program control block (PCB).
+/** Set ELF-related PCB entries.
  *
  * Fills the program control block @a pcb with information from
@@ -121,347 +92,11 @@
  *
  * @param info	Program info structure
- * @return EOK on success or negative error code
+ * @param pcb PCB
  */
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
+void elf_set_pcb(elf_info_t *info, pcb_t *pcb)
 {
-	pcb->entry = info->entry;
-	pcb->dynamic = info->dynamic;
-	pcb->rtld_runtime = NULL;
-}
-
-
-/** Load an ELF binary.
- *
- * The @a elf structure contains the loader state, including
- * an open file, from which the binary will be loaded,
- * a pointer to the @c info structure etc.
- *
- * @param elf		Pointer to loader state buffer.
- * @param so_bias	Bias to use if the file is a shared object.
- * @return EE_OK on success or EE_xx error code.
- */
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
-{
-	elf_header_t header_buf;
-	elf_header_t *header = &header_buf;
-	int i, rc;
-
-	rc = read(elf->fd, header, sizeof(elf_header_t));
-	if (rc != sizeof(elf_header_t)) {
-		DPRINTF("Read error.\n"); 
-		return EE_INVALID;
-	}
-
-	elf->header = header;
-
-	/* Identify ELF */
-	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
-	    header->e_ident[EI_MAG1] != ELFMAG1 || 
-	    header->e_ident[EI_MAG2] != ELFMAG2 ||
-	    header->e_ident[EI_MAG3] != ELFMAG3) {
-		DPRINTF("Invalid header.\n");
-		return EE_INVALID;
-	}
-	
-	/* Identify ELF compatibility */
-	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
-	    header->e_machine != ELF_MACHINE || 
-	    header->e_ident[EI_VERSION] != EV_CURRENT ||
-	    header->e_version != EV_CURRENT ||
-	    header->e_ident[EI_CLASS] != ELF_CLASS) {
-		DPRINTF("Incompatible data/version/class.\n");
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
-		DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
-		    sizeof(elf_segment_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_shentsize != sizeof(elf_section_header_t)) {
-		DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
-		    sizeof(elf_section_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	/* Check if the object type is supported. */
-	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
-		DPRINTF("Object type %d is not supported\n", header->e_type);
-		return EE_UNSUPPORTED;
-	}
-
-	/* Shared objects can be loaded with a bias */
-	if (header->e_type == ET_DYN)
-		elf->bias = so_bias;
-	else
-		elf->bias = 0;
-
-	elf->info->interp = NULL;
-	elf->info->dynamic = NULL;
-
-	/* Walk through all segment headers and process them. */
-	for (i = 0; i < header->e_phnum; i++) {
-		elf_segment_header_t segment_hdr;
-
-		/* Seek to start of segment header */
-		lseek(elf->fd, header->e_phoff
-		        + i * sizeof(elf_segment_header_t), SEEK_SET);
-
-		rc = read(elf->fd, &segment_hdr,
-		    sizeof(elf_segment_header_t));
-		if (rc != sizeof(elf_segment_header_t)) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = segment_header(elf, &segment_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	DPRINTF("Parse sections.\n");
-
-	/* Inspect all section headers and proccess them. */
-	for (i = 0; i < header->e_shnum; i++) {
-		elf_section_header_t section_hdr;
-
-		/* Seek to start of section header */
-		lseek(elf->fd, header->e_shoff
-		    + i * sizeof(elf_section_header_t), SEEK_SET);
-
-		rc = read(elf->fd, &section_hdr,
-		    sizeof(elf_section_header_t));
-		if (rc != sizeof(elf_section_header_t)) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = section_header(elf, &section_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	elf->info->entry =
-	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
-
-	DPRINTF("Done.\n");
-
-	return EE_OK;
-}
-
-/** Print error message according to error code.
- *
- * @param rc Return code returned by elf_load().
- *
- * @return NULL terminated description of error.
- */
-const char *elf_error(unsigned int rc)
-{
-	assert(rc < sizeof(error_codes) / sizeof(char *));
-
-	return error_codes[rc];
-}
-
-/** Process segment header.
- *
- * @param entry	Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	switch (entry->p_type) {
-	case PT_NULL:
-	case PT_PHDR:
-	case PT_NOTE:
-		break;
-	case PT_LOAD:
-		return load_segment(elf, entry);
-		break;
-	case PT_INTERP:
-		/* Assume silently interp == "/app/dload" */
-		elf->info->interp = "/app/dload";
-		break;
-	case PT_DYNAMIC:
-		/* Record pointer to dynamic section into info structure */
-		elf->info->dynamic =
-		    (void *)((uint8_t *)entry->p_vaddr + elf->bias);
-		DPRINTF("dynamic section found at 0x%x\n",
-			(uintptr_t)elf->info->dynamic);
-		break;
-	case 0x70000000:
-		/* FIXME: MIPS reginfo */
-		break;
-	case PT_SHLIB:
-//	case PT_LOPROC:
-//	case PT_HIPROC:
-	default:
-		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
-		return EE_UNSUPPORTED;
-		break;
-	}
-	return EE_OK;
-}
-
-/** Load segment described by program header entry.
- *
- * @param elf	Loader state.
- * @param entry Program header entry describing segment to be loaded.
- *
- * @return EE_OK on success, error code otherwise.
- */
-int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	void *a;
-	int flags = 0;
-	uintptr_t bias;
-	uintptr_t base;
-	void *seg_ptr;
-	uintptr_t seg_addr;
-	size_t mem_sz;
-	ssize_t rc;
-
-	bias = elf->bias;
-
-	seg_addr = entry->p_vaddr + bias;
-	seg_ptr = (void *) seg_addr;
-
-	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
-		entry->p_memsz);
-
-	if (entry->p_align > 1) {
-		if ((entry->p_offset % entry->p_align) !=
-		    (seg_addr % entry->p_align)) {
-			DPRINTF("Align check 1 failed offset%%align=%d, "
-			    "vaddr%%align=%d\n",
-			    entry->p_offset % entry->p_align,
-			    seg_addr % entry->p_align
-			);
-			return EE_INVALID;
-		}
-	}
-
-	/* Final flags that will be set for the memory area */
-
-	if (entry->p_flags & PF_X)
-		flags |= AS_AREA_EXEC;
-	if (entry->p_flags & PF_W)
-		flags |= AS_AREA_WRITE;
-	if (entry->p_flags & PF_R)
-		flags |= AS_AREA_READ;
-	flags |= AS_AREA_CACHEABLE;
-	
-	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
-	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
-
-	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
-	    (void *) (entry->p_vaddr + bias +
-	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
-
-	/*
-	 * For the course of loading, the area needs to be readable
-	 * and writeable.
-	 */
-	a = as_area_create((uint8_t *) base + bias, mem_sz,
-	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	if (a == AS_MAP_FAILED) {
-		DPRINTF("memory mapping failed (0x%x, %d)\n",
-		    base + bias, mem_sz);
-		return EE_MEMORY;
-	}
-
-	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
-	    (void *) (base + bias), mem_sz, flags, (void *) a);
-
-	/*
-	 * Load segment data
-	 */
-	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
-	if (rc < 0) {
-		printf("seek error\n");
-		return EE_INVALID;
-	}
-
-/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
-	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
-
-	/* Long reads are not possible yet. Load segment piecewise. */
-
-	unsigned left, now;
-	uint8_t *dp;
-
-	left = entry->p_filesz;
-	dp = seg_ptr;
-
-	while (left > 0) {
-		now = 16384;
-		if (now > left) now = left;
-
-		rc = read(elf->fd, dp, now);
-
-		if (rc != (ssize_t) now) { 
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		left -= now;
-		dp += now;
-	}
-
-	/*
-	 * The caller wants to modify the segments first. He will then
-	 * need to set the right access mode and ensure SMC coherence.
-	 */
-	if ((elf->flags & ELDF_RW) != 0) return EE_OK;
-
-//	printf("set area flags to %d\n", flags);
-	rc = as_area_change_flags(seg_ptr, flags);
-	if (rc != 0) {
-		DPRINTF("Failed to set memory area flags.\n");
-		return EE_MEMORY;
-	}
-
-	if (flags & AS_AREA_EXEC) {
-		/* Enforce SMC coherence for the segment */
-		if (smc_coherence(seg_ptr, entry->p_filesz))
-			return EE_MEMORY;
-	}
-
-	return EE_OK;
-}
-
-/** Process section header.
- *
- * @param elf	Loader state.
- * @param entry Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
-{
-	switch (entry->sh_type) {
-	case SHT_PROGBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tdata */
-		}
-		break;
-	case SHT_NOBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tbss */
-		}
-		break;
-	case SHT_DYNAMIC:
-		/* Record pointer to dynamic section into info structure */
-		elf->info->dynamic =
-		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
-		DPRINTF("Dynamic section found at %p.\n",
-		    (void *) elf->info->dynamic);
-		break;
-	default:
-		break;
-	}
-	
-	return EE_OK;
+	pcb->entry = info->finfo.entry;
+	pcb->dynamic = info->finfo.dynamic;
+	pcb->rtld_runtime = info->env;
 }
 
Index: uspace/lib/c/generic/elf/elf_mod.c
===================================================================
--- uspace/lib/c/generic/elf/elf_mod.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
+++ uspace/lib/c/generic/elf/elf_mod.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+
+/**
+ * @file
+ * @brief	Userspace ELF module loader.
+ *
+ * This module allows loading ELF binaries (both executables and
+ * shared objects) from VFS. The current implementation allocates
+ * anonymous memory, fills it with segment data and then adjusts
+ * the memory areas' flags to the final value. In the future,
+ * the segments will be mapped directly from the file.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <align.h>
+#include <assert.h>
+#include <as.h>
+#include <elf/elf.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <smc.h>
+#include <loader/pcb.h>
+#include <entry_point.h>
+
+#include <elf/elf_load.h>
+
+#define DPRINTF(...)
+
+static const char *error_codes[] = {
+	"no error",
+	"invalid image",
+	"address space error",
+	"incompatible image",
+	"unsupported image type",
+	"irrecoverable error"
+};
+
+static unsigned int elf_load_module(elf_ld_t *elf, size_t so_bias);
+static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
+static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
+static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
+
+/** Load ELF binary from a file.
+ *
+ * Load an ELF binary from the specified file. If the file is
+ * an executable program, it is loaded unbiased. If it is a shared
+ * object, it is loaded with the bias @a so_bias. Some information
+ * extracted from the binary is stored in a elf_info_t structure
+ * pointed to by @a info.
+ *
+ * @param file_name Path to the ELF file.
+ * @param so_bias   Bias to use if the file is a shared object.
+ * @param info      Pointer to a structure for storing information
+ *                  extracted from the binary.
+ *
+ * @return EOK on success or negative error code.
+ *
+ */
+int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
+    elf_finfo_t *info)
+{
+	elf_ld_t elf;
+
+	int fd;
+	int rc;
+
+	fd = open(file_name, O_RDONLY);
+	if (fd < 0) {
+		DPRINTF("failed opening file\n");
+		return -1;
+	}
+
+	elf.fd = fd;
+	elf.info = info;
+	elf.flags = flags;
+
+	rc = elf_load_module(&elf, so_bias);
+
+	close(fd);
+
+	return rc;
+}
+
+/** Load an ELF binary.
+ *
+ * The @a elf structure contains the loader state, including
+ * an open file, from which the binary will be loaded,
+ * a pointer to the @c info structure etc.
+ *
+ * @param elf		Pointer to loader state buffer.
+ * @param so_bias	Bias to use if the file is a shared object.
+ * @return EE_OK on success or EE_xx error code.
+ */
+static unsigned int elf_load_module(elf_ld_t *elf, size_t so_bias)
+{
+	elf_header_t header_buf;
+	elf_header_t *header = &header_buf;
+	int i, rc;
+
+	rc = read(elf->fd, header, sizeof(elf_header_t));
+	if (rc != sizeof(elf_header_t)) {
+		DPRINTF("Read error.\n"); 
+		return EE_INVALID;
+	}
+
+	elf->header = header;
+
+	/* Identify ELF */
+	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
+	    header->e_ident[EI_MAG1] != ELFMAG1 || 
+	    header->e_ident[EI_MAG2] != ELFMAG2 ||
+	    header->e_ident[EI_MAG3] != ELFMAG3) {
+		DPRINTF("Invalid header.\n");
+		return EE_INVALID;
+	}
+	
+	/* Identify ELF compatibility */
+	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
+	    header->e_machine != ELF_MACHINE || 
+	    header->e_ident[EI_VERSION] != EV_CURRENT ||
+	    header->e_version != EV_CURRENT ||
+	    header->e_ident[EI_CLASS] != ELF_CLASS) {
+		DPRINTF("Incompatible data/version/class.\n");
+		return EE_INCOMPATIBLE;
+	}
+
+	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
+		DPRINTF("e_phentsize: %u != %zu\n", header->e_phentsize,
+		    sizeof(elf_segment_header_t));
+		return EE_INCOMPATIBLE;
+	}
+
+	if (header->e_shentsize != sizeof(elf_section_header_t)) {
+		DPRINTF("e_shentsize: %u != %zu\n", header->e_shentsize,
+		    sizeof(elf_section_header_t));
+		return EE_INCOMPATIBLE;
+	}
+
+	/* Check if the object type is supported. */
+	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
+		DPRINTF("Object type %d is not supported\n", header->e_type);
+		return EE_UNSUPPORTED;
+	}
+
+	/* Shared objects can be loaded with a bias */
+	if (header->e_type == ET_DYN)
+		elf->bias = so_bias;
+	else
+		elf->bias = 0;
+
+	elf->info->interp = NULL;
+	elf->info->dynamic = NULL;
+
+	/* Walk through all segment headers and process them. */
+	for (i = 0; i < header->e_phnum; i++) {
+		elf_segment_header_t segment_hdr;
+
+		/* Seek to start of segment header */
+		lseek(elf->fd, header->e_phoff
+		        + i * sizeof(elf_segment_header_t), SEEK_SET);
+
+		rc = read(elf->fd, &segment_hdr,
+		    sizeof(elf_segment_header_t));
+		if (rc != sizeof(elf_segment_header_t)) {
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		rc = segment_header(elf, &segment_hdr);
+		if (rc != EE_OK)
+			return rc;
+	}
+
+	DPRINTF("Parse sections.\n");
+
+	/* Inspect all section headers and proccess them. */
+	for (i = 0; i < header->e_shnum; i++) {
+		elf_section_header_t section_hdr;
+
+		/* Seek to start of section header */
+		lseek(elf->fd, header->e_shoff
+		    + i * sizeof(elf_section_header_t), SEEK_SET);
+
+		rc = read(elf->fd, &section_hdr,
+		    sizeof(elf_section_header_t));
+		if (rc != sizeof(elf_section_header_t)) {
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		rc = section_header(elf, &section_hdr);
+		if (rc != EE_OK)
+			return rc;
+	}
+
+	elf->info->entry =
+	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
+
+	DPRINTF("Done.\n");
+
+	return EE_OK;
+}
+
+/** Print error message according to error code.
+ *
+ * @param rc Return code returned by elf_load().
+ *
+ * @return NULL terminated description of error.
+ */
+const char *elf_error(unsigned int rc)
+{
+	assert(rc < sizeof(error_codes) / sizeof(char *));
+
+	return error_codes[rc];
+}
+
+/** Process segment header.
+ *
+ * @param entry	Segment header.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
+{
+	switch (entry->p_type) {
+	case PT_NULL:
+	case PT_PHDR:
+	case PT_NOTE:
+		break;
+	case PT_LOAD:
+		return load_segment(elf, entry);
+		break;
+	case PT_INTERP:
+		/* Assume silently interp == "/app/dload" */
+		elf->info->interp = "/app/dload";
+		break;
+	case PT_DYNAMIC:
+		/* Record pointer to dynamic section into info structure */
+		elf->info->dynamic =
+		    (void *)((uint8_t *)entry->p_vaddr + elf->bias);
+		DPRINTF("dynamic section found at %p\n",
+			(void *)elf->info->dynamic);
+		break;
+	case 0x70000000:
+		/* FIXME: MIPS reginfo */
+		break;
+	case PT_SHLIB:
+//	case PT_LOPROC:
+//	case PT_HIPROC:
+	default:
+		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
+		return EE_UNSUPPORTED;
+		break;
+	}
+	return EE_OK;
+}
+
+/** Load segment described by program header entry.
+ *
+ * @param elf	Loader state.
+ * @param entry Program header entry describing segment to be loaded.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
+{
+	void *a;
+	int flags = 0;
+	uintptr_t bias;
+	uintptr_t base;
+	void *seg_ptr;
+	uintptr_t seg_addr;
+	size_t mem_sz;
+	ssize_t rc;
+
+	bias = elf->bias;
+
+	seg_addr = entry->p_vaddr + bias;
+	seg_ptr = (void *) seg_addr;
+
+	DPRINTF("Load segment at addr %p, size 0x%zx\n", (void *) seg_addr,
+		entry->p_memsz);
+
+	if (entry->p_align > 1) {
+		if ((entry->p_offset % entry->p_align) !=
+		    (seg_addr % entry->p_align)) {
+			DPRINTF("Align check 1 failed offset%%align=0x%zx, "
+			    "vaddr%%align=0x%zx\n",
+			    entry->p_offset % entry->p_align,
+			    seg_addr % entry->p_align);
+			return EE_INVALID;
+		}
+	}
+
+	/* Final flags that will be set for the memory area */
+
+	if (entry->p_flags & PF_X)
+		flags |= AS_AREA_EXEC;
+	if (entry->p_flags & PF_W)
+		flags |= AS_AREA_WRITE;
+	if (entry->p_flags & PF_R)
+		flags |= AS_AREA_READ;
+	flags |= AS_AREA_CACHEABLE;
+	
+	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
+	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
+
+	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
+	    (void *) (entry->p_vaddr + bias +
+	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
+
+	/*
+	 * For the course of loading, the area needs to be readable
+	 * and writeable.
+	 */
+	a = as_area_create((uint8_t *) base + bias, mem_sz,
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	if (a == AS_MAP_FAILED) {
+		DPRINTF("memory mapping failed (%p, %zu)\n",
+		    (void *) (base + bias), mem_sz);
+		return EE_MEMORY;
+	}
+
+	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
+	    (void *) (base + bias), mem_sz, flags, (void *) a);
+
+	/*
+	 * Load segment data
+	 */
+	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
+	if (rc < 0) {
+		printf("seek error\n");
+		return EE_INVALID;
+	}
+
+/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
+	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
+
+	/* Long reads are not possible yet. Load segment piecewise. */
+
+	unsigned left, now;
+	uint8_t *dp;
+
+	left = entry->p_filesz;
+	dp = seg_ptr;
+
+	while (left > 0) {
+		now = 16384;
+		if (now > left) now = left;
+
+		rc = read(elf->fd, dp, now);
+
+		if (rc != (ssize_t) now) { 
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		left -= now;
+		dp += now;
+	}
+
+	/*
+	 * The caller wants to modify the segments first. He will then
+	 * need to set the right access mode and ensure SMC coherence.
+	 */
+	if ((elf->flags & ELDF_RW) != 0) return EE_OK;
+
+//	printf("set area flags to %d\n", flags);
+	rc = as_area_change_flags(seg_ptr, flags);
+	if (rc != 0) {
+		DPRINTF("Failed to set memory area flags.\n");
+		return EE_MEMORY;
+	}
+
+	if (flags & AS_AREA_EXEC) {
+		/* Enforce SMC coherence for the segment */
+		if (smc_coherence(seg_ptr, entry->p_filesz))
+			return EE_MEMORY;
+	}
+
+	return EE_OK;
+}
+
+/** Process section header.
+ *
+ * @param elf	Loader state.
+ * @param entry Segment header.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
+{
+	switch (entry->sh_type) {
+	case SHT_PROGBITS:
+		if (entry->sh_flags & SHF_TLS) {
+			/* .tdata */
+		}
+		break;
+	case SHT_NOBITS:
+		if (entry->sh_flags & SHF_TLS) {
+			/* .tbss */
+		}
+		break;
+	case SHT_DYNAMIC:
+		/* Record pointer to dynamic section into info structure */
+		elf->info->dynamic =
+		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
+		DPRINTF("Dynamic section found at %p.\n",
+		    (void *) elf->info->dynamic);
+		break;
+	default:
+		break;
+	}
+	
+	return EE_OK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/generic/libc.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -89,7 +89,7 @@
 	char **argv;
 	
-#ifdef __IN_SHARED_LIBC__
+#ifdef CONFIG_RTLD
 	if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
-		runtime_env = (runtime_env_t *) __pcb->rtld_runtime;
+		runtime_env = (rtld_t *) __pcb->rtld_runtime;
 	}
 #endif
Index: uspace/lib/c/generic/rtld/module.c
===================================================================
--- uspace/lib/c/generic/rtld/module.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/generic/rtld/module.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -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 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/generic/rtld/rtld.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -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 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/generic/rtld/symbol.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -39,4 +39,5 @@
 
 #include <elf/elf.h>
+#include <rtld/module.h>
 #include <rtld/rtld.h>
 #include <rtld/rtld_debug.h>
@@ -111,8 +112,11 @@
  * @param name		Name of the symbol to search for.
  * @param start		Module in which to start the search..
+ * @param flags		@c ssf_none or @c ssf_noroot to not look for the symbol
+ *			in @a start
  * @param mod		(output) Will be filled with a pointer to the module 
  *			that contains the symbol.
  */
-elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod)
+elf_symbol_t *symbol_bfs_find(const char *name, module_t *start,
+    symbol_search_flags_t flags, module_t **mod)
 {
 	module_t *m, *dm;
@@ -129,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 */
@@ -145,10 +149,13 @@
 		list_remove(&m->queue_link);
 
-		s = def_find_in_module(name, m);
-		if (s != NULL) {
-			/* Symbol found */
-			sym = s;
-			*mod = m;
-			break;
+		/* If ssf_noroot is specified, do not look in start module */
+		if (m != start || (flags & ssf_noroot) == 0) { 
+			s = def_find_in_module(name, m);
+			if (s != NULL) {
+				/* Symbol found */
+				sym = s;
+				*mod = m;
+				break;
+			}
 		}
 
@@ -179,5 +186,5 @@
 
 
-/** Find the definition of a symbol..
+/** Find the definition of a symbol.
  *
  * By definition in System V ABI, if module origin has the flag DT_SYMBOLIC,
@@ -188,8 +195,11 @@
  * @param name		Name of the symbol to search for.
  * @param origin	Module in which the dependency originates.
+ * @param flags		@c ssf_none or @c ssf_noroot to not look for the symbol
+ *			in the executable program.
  * @param mod		(output) Will be filled with a pointer to the module 
  *			that contains the symbol.
  */
-elf_symbol_t *symbol_def_find(const char *name, module_t *origin, module_t **mod)
+elf_symbol_t *symbol_def_find(const char *name, module_t *origin,
+    symbol_search_flags_t flags, module_t **mod)
 {
 	elf_symbol_t *s;
@@ -210,10 +220,10 @@
 	/* 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, mod);
+		return symbol_bfs_find(name, origin->rtld->program, flags, mod);
 	} else {
 		/* Program is static -- start with @a origin as root. */
-		return symbol_bfs_find(name, origin, mod);
+		return symbol_bfs_find(name, origin, ssf_none, mod);
 	}
 }
Index: uspace/lib/c/include/elf/elf_load.h
===================================================================
--- uspace/lib/c/include/elf/elf_load.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/include/elf/elf_load.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2006 Sergey Bondari
- * Copyright (c) 2008 Jiri Svoboda
+ * Copyright (c) 2016 Jiri Svoboda
  * All rights reserved.
  *
@@ -32,5 +31,5 @@
  */
 /** @file
- * @brief ELF loader structures and public functions.
+ * @brief
  */
 
@@ -38,61 +37,14 @@
 #define ELF_LOAD_H_
 
-#include <elf/elf.h>
-#include <sys/types.h>
-#include <loader/pcb.h>
+#include <elf/elf_mod.h>
 
-/**
- * ELF error return codes
- */
-#define EE_OK			0	/* No error */
-#define EE_INVALID		1	/* Invalid ELF image */
-#define EE_MEMORY		2	/* Cannot allocate address space */
-#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
-#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
-#define EE_LOADER		5	/* The image is actually a program loader. */
-#define EE_IRRECOVERABLE	6
-
-typedef enum {
-	/** Leave all segments in RW access mode. */
-	ELDF_RW = 1
-} eld_flags_t;
-
-/**
- * Some data extracted from the headers are stored here
- */
+/** Information on loaded ELF program */
 typedef struct {
-	/** Entry point */
-	entry_point_t entry;
-
-	/** ELF interpreter name or NULL if statically-linked */
-	const char *interp;
-
-	/** Pointer to the dynamic section */
-	void *dynamic;
+	elf_finfo_t finfo;
+	struct rtld *env;
 } elf_info_t;
 
-/**
- * Holds information about an ELF binary being loaded.
- */
-typedef struct {
-	/** Filedescriptor of the file from which we are loading */
-	int fd;
-
-	/** Difference between run-time addresses and link-time addresses */
-	uintptr_t bias;
-
-	/** Flags passed to the ELF loader. */
-	eld_flags_t flags;
-
-	/** A copy of the ELF file header */
-	elf_header_t *header;
-
-	/** Store extracted info here */
-	elf_info_t *info;
-} elf_ld_t;
-
-extern const char *elf_error(unsigned int);
-extern int elf_load_file(const char *, size_t, eld_flags_t, elf_info_t *);
-extern void elf_create_pcb(elf_info_t *, pcb_t *);
+extern int elf_load(const char *, elf_info_t *);
+extern void elf_set_pcb(elf_info_t *, pcb_t *);
 
 #endif
Index: uspace/lib/c/include/elf/elf_mod.h
===================================================================
--- uspace/lib/c/include/elf/elf_mod.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
+++ uspace/lib/c/include/elf/elf_mod.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * Copyright (c) 2008 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ * @brief ELF loader structures and public functions.
+ */
+
+#ifndef ELF_MOD_H_
+#define ELF_MOD_H_
+
+#include <elf/elf.h>
+#include <sys/types.h>
+#include <loader/pcb.h>
+
+/**
+ * ELF error return codes
+ */
+#define EE_OK			0	/* No error */
+#define EE_INVALID		1	/* Invalid ELF image */
+#define EE_MEMORY		2	/* Cannot allocate address space */
+#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
+#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
+#define EE_LOADER		5	/* The image is actually a program loader. */
+#define EE_IRRECOVERABLE	6
+
+typedef enum {
+	/** Leave all segments in RW access mode. */
+	ELDF_RW = 1
+} eld_flags_t;
+
+/**
+ * Some data extracted from the headers are stored here
+ */
+typedef struct {
+	/** Entry point */
+	entry_point_t entry;
+
+	/** ELF interpreter name or NULL if statically-linked */
+	const char *interp;
+
+	/** Pointer to the dynamic section */
+	void *dynamic;
+} elf_finfo_t;
+
+/**
+ * Holds information about an ELF binary being loaded.
+ */
+typedef struct {
+	/** Filedescriptor of the file from which we are loading */
+	int fd;
+
+	/** Difference between run-time addresses and link-time addresses */
+	uintptr_t bias;
+
+	/** Flags passed to the ELF loader. */
+	eld_flags_t flags;
+
+	/** A copy of the ELF file header */
+	elf_header_t *header;
+
+	/** Store extracted info here */
+	elf_finfo_t *info;
+} elf_ld_t;
+
+extern const char *elf_error(unsigned int);
+extern int elf_load_file(const char *, size_t, eld_flags_t, elf_finfo_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/loader/pcb.h
===================================================================
--- uspace/lib/c/include/loader/pcb.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/include/loader/pcb.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -69,5 +69,5 @@
 	/** Pointer to ELF dynamic section of the program. */
 	void *dynamic;
-	/** Pointer to dynamic linker state structure (runtime_env_t). */
+	/** Pointer to dynamic linker state structure (rtld_t). */
 	void *rtld_runtime;
 } pcb_t;
Index: uspace/lib/c/include/rtld/module.h
===================================================================
--- uspace/lib/c/include/rtld/module.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/include/rtld/module.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -39,33 +39,14 @@
 #include <rtld/dynamic.h>
 #include <adt/list.h>
+#include <types/rtld/module.h>
+#include <types/rtld/rtld.h>
 
-typedef struct module {
-	dyn_info_t dyn;
-	size_t bias;
+extern void module_process_relocs(module_t *);
+extern module_t *module_find(rtld_t *, const char *);
+extern module_t *module_load(rtld_t *, const char *);
+extern void module_load_deps(module_t *);
 
-	/** Array of pointers to directly dependent modules */
-	struct module **deps;
-	/** Number of fields in deps */
-	size_t n_deps;
-
-	/** True iff relocations have already been processed in this module. */
-	bool relocated;
-
-	/** Link to list of all modules in runtime environment */
-	link_t modules_link;
-
-	/** Link to BFS queue. Only used when doing a BFS of the module graph */
-	link_t queue_link;
-	/** Tag for modules already processed during a BFS */
-	bool bfs_tag;
-} module_t;
-
-void module_process_relocs(module_t *m);
-module_t *module_find(const char *name);
-module_t *module_load(const char *name);
-void module_load_deps(module_t *m);
-
-void modules_process_relocs(module_t *start);
-void modules_untag(void);
+extern void modules_process_relocs(rtld_t *, module_t *);
+extern void modules_untag(rtld_t *);
 
 #endif
Index: uspace/lib/c/include/rtld/rtld.h
===================================================================
--- uspace/lib/c/include/rtld/rtld.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/include/rtld/rtld.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -36,26 +36,15 @@
 #define LIBC_RTLD_H_
 
+#include <adt/list.h>
+#include <elf/elf_mod.h>
 #include <sys/types.h>
-#include <adt/list.h>
 
 #include <rtld/dynamic.h>
-#include <rtld/module.h>
+#include <types/rtld/rtld.h>
 
-typedef struct {
-	elf_dyn_t *rtld_dynamic;
-	module_t rtld;
-
-	module_t *program;
-
-	/** List of all loaded modules including rtld and the program */
-	list_t modules;
-
-	/** Temporary hack to place each module at different address. */
-	uintptr_t next_bias;
-} runtime_env_t;
-
-extern runtime_env_t *runtime_env;
+extern rtld_t *runtime_env;
 
 extern void rtld_init_static(void);
+extern int rtld_prog_process(elf_finfo_t *, rtld_t **);
 
 #endif
Index: uspace/lib/c/include/rtld/rtld_debug.h
===================================================================
--- uspace/lib/c/include/rtld/rtld_debug.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/include/rtld/rtld_debug.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -36,4 +36,6 @@
 #define LIBC_RTLD_RTLD_DEBUG_H_
 
+#include <stdio.h>
+
 /* Define to enable debugging mode. */
 #undef RTLD_DEBUG
Index: uspace/lib/c/include/rtld/symbol.h
===================================================================
--- uspace/lib/c/include/rtld/symbol.h	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/c/include/rtld/symbol.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -39,7 +39,17 @@
 #include <rtld/rtld.h>
 
-elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod);
-elf_symbol_t *symbol_def_find(const char *name, module_t *origin, module_t **mod);
-void *symbol_get_addr(elf_symbol_t *sym, module_t *m);
+/** Symbol search flags */
+typedef enum {
+	/** No flags */
+	ssf_none = 0,
+	/** Do not search tree root */
+	ssf_noroot = 0x1
+} symbol_search_flags_t;
+
+extern elf_symbol_t *symbol_bfs_find(const char *, module_t *,
+    symbol_search_flags_t, module_t **);
+extern elf_symbol_t *symbol_def_find(const char *, module_t *,
+    symbol_search_flags_t, module_t **);
+extern void *symbol_get_addr(elf_symbol_t *, module_t *);
 
 #endif
Index: uspace/lib/c/include/types/rtld/module.h
===================================================================
--- uspace/lib/c/include/types/rtld/module.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
+++ uspace/lib/c/include/types/rtld/module.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_TYPES_RTLD_MODULE_H_
+#define LIBC_TYPES_RTLD_MODULE_H_
+
+#include <adt/list.h>
+#include <sys/types.h>
+
+typedef struct module {
+	dyn_info_t dyn;
+	size_t bias;
+
+	/** Containing rtld */
+	struct rtld *rtld;
+	/** Array of pointers to directly dependent modules */
+	struct module **deps;
+	/** Number of fields in deps */
+	size_t n_deps;
+
+	/** True iff relocations have already been processed in this module. */
+	bool relocated;
+
+	/** Link to list of all modules in runtime environment */
+	link_t modules_link;
+
+	/** Link to BFS queue. Only used when doing a BFS of the module graph */
+	link_t queue_link;
+	/** Tag for modules already processed during a BFS */
+	bool bfs_tag;
+} module_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/types/rtld/rtld.h
===================================================================
--- uspace/lib/c/include/types/rtld/rtld.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
+++ uspace/lib/c/include/types/rtld/rtld.h	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2008 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_TYPES_RTLD_RTLD_H_
+#define LIBC_TYPES_RTLD_RTLD_H_
+
+#include <adt/list.h>
+#include <elf/elf_mod.h>
+#include <sys/types.h>
+
+#include <types/rtld/module.h>
+
+typedef struct rtld {
+	elf_dyn_t *rtld_dynamic;
+	module_t rtld;
+
+	module_t *program;
+
+	/** List of all loaded modules including rtld and the program */
+	list_t modules;
+
+	/** Temporary hack to place each module at different address. */
+	uintptr_t next_bias;
+} rtld_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/draw/Makefile
===================================================================
--- uspace/lib/draw/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/draw/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -30,5 +30,5 @@
 LIBRARY = libdraw
 SLIBRARY = libdraw.so.0.0
-LSONAME = libdraw.so0
+LSONAME = libdraw.so.0
 EXTRA_CFLAGS += -I$(LIBSOFTREND_PREFIX) -I$(LIBCOMPRESS_PREFIX)
 
Index: uspace/lib/graph/Makefile
===================================================================
--- uspace/lib/graph/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/graph/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -30,5 +30,5 @@
 LIBRARY = libgraph
 SLIBRARY = libgraph.so.0.0
-LSONAME = libgraph.so0
+LSONAME = libgraph.so.0
 
 SOURCES = \
Index: uspace/lib/gui/Makefile
===================================================================
--- uspace/lib/gui/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/gui/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -30,5 +30,5 @@
 LIBRARY = libgui
 SLIBRARY = libgui.so.0.0
-LSONAME = libgui.so0
+LSONAME = libgui.so.0
 EXTRA_CFLAGS += -I$(LIBDRAW_PREFIX) -I$(LIBSOFTREND_PREFIX) -I$(LIBGRAPH_PREFIX)
 
Index: uspace/lib/http/Makefile
===================================================================
--- uspace/lib/http/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/http/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -30,5 +30,5 @@
 LIBRARY = libhttp
 SLIBRARY = libhttp.so.0.0
-LSONAME = libhttp.so0
+LSONAME = libhttp.so.0
 EXTRA_CFLAGS += -Iinclude
 
Index: uspace/lib/math/Makefile
===================================================================
--- uspace/lib/math/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/math/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -34,5 +34,5 @@
 LIBRARY = libmath
 SLIBRARY = libmath.so.0.0
-LSONAME = libmath.so0
+LSONAME = libmath.so.0
 MATH = y
 
Index: uspace/lib/posix/Makefile
===================================================================
--- uspace/lib/posix/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/posix/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -31,5 +31,5 @@
 LIBRARY = libposix
 SLIBRARY = libposix.so.0.0
-LSONAME = libposix.so0
+LSONAME = libposix.so.0
 
 EXTRA_CFLAGS = -Iinclude/
Index: uspace/lib/softint/Makefile
===================================================================
--- uspace/lib/softint/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/softint/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -32,5 +32,5 @@
 LIBRARY = libsoftint
 SLIBRARY = libsoftint.so.0.0
-LSONAME = libsofti.so0
+LSONAME = libsoftint.so.0
 
 SOURCES = \
Index: uspace/lib/softrend/Makefile
===================================================================
--- uspace/lib/softrend/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/softrend/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -30,5 +30,5 @@
 LIBRARY = libsoftrend
 SLIBRARY = libsoftrend.so.0.0
-LSONAME = libsoftrend.so0
+LSONAME = libsoftrend.so.0
 MATH = y
 
Index: uspace/lib/uri/Makefile
===================================================================
--- uspace/lib/uri/Makefile	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/lib/uri/Makefile	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -30,5 +30,5 @@
 LIBRARY = liburi
 SLIBRARY = liburi.so.0.0
-LSONAME = liburi.so0
+LSONAME = liburi.so.0
 #EXTRA_CFLAGS += 
 
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 73b3ecde730c3b8a3a21834f6c65380d45bf9991)
+++ uspace/srv/loader/main.c	(revision 054476d01aca9bd28135fce64c7c46d84fe7398c)
@@ -63,12 +63,4 @@
 #include <vfs/vfs.h>
 
-#ifdef CONFIG_RTLD
-#include <rtld/rtld.h>
-#include <rtld/dynamic.h>
-#include <rtld/module.h>
-
-static int ldr_load_dyn_linked(elf_info_t *p_info);
-#endif
-
 #define DPRINTF(...)
 
@@ -96,10 +88,4 @@
 /** Used to limit number of connections to one. */
 static bool connected = false;
-
-#ifdef CONFIG_RTLD
-/** State structure of the dynamic linker. */
-runtime_env_t dload_re;
-static module_t prog_mod;
-#endif
 
 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
@@ -268,5 +254,5 @@
 	int rc;
 	
-	rc = elf_load_file(pathname, 0, 0, &prog_info);
+	rc = elf_load(pathname, &prog_info);
 	if (rc != EE_OK) {
 		DPRINTF("Failed to load executable '%s'.\n", pathname);
@@ -275,5 +261,5 @@
 	}
 	
-	elf_create_pcb(&prog_info, &pcb);
+	elf_set_pcb(&prog_info, &pcb);
 	
 	pcb.cwd = cwd;
@@ -283,73 +269,9 @@
 	
 	pcb.filc = filc;
-	
-	if (prog_info.interp == NULL) {
-		/* Statically linked program */
-		async_answer_0(rid, EOK);
-		return 0;
-	}
-	
-	DPRINTF("Binary is dynamically linked.\n");
-#ifdef CONFIG_RTLD
-	DPRINTF(" - pcb address: %p\n", &pcb);
-	DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
-
-	rc = ldr_load_dyn_linked(&prog_info);
-#else
-	rc = ENOTSUP;
-#endif
+	printf("dynamic=%p rtld_env=%p\n", pcb.dynamic, pcb.rtld_runtime);
+	
 	async_answer_0(rid, rc);
 	return 0;
 }
-
-#ifdef CONFIG_RTLD
-
-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);
-	list_append(&prog_mod.modules_link, &runtime_env->modules);
-
-	/* 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;
-}
-#endif
 
 /** Run the previously loaded program.
@@ -374,5 +296,5 @@
 	async_answer_0(rid, EOK);
 	DPRINTF("Jump to entry point at %p\n", pcb.entry);
-	entry_point_jmp(prog_info.entry, &pcb);
+	entry_point_jmp(prog_info.finfo.entry, &pcb);
 	
 	/* Not reached */
