Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 45454e9b4eae43c54f3381318875dcf28b2419a0)
+++ uspace/app/trace/trace.c	(revision 4470e2627030413dc38c0d3b98d9c6a3e1672564)
@@ -43,4 +43,5 @@
 #include <async.h>
 #include <task.h>
+#include <loader/loader.h>
 
 // Temporary: service and method names
@@ -71,9 +72,47 @@
 static proto_t *proto_console;
 static task_id_t task_id;
+static loader_t *task_ldr;
 
 /** Combination of events/data to print. */
 display_mask_t display_mask;
 
-static int task_connect(task_id_t task_id)
+static int program_run_fibril(void *arg);
+
+static void program_run(void)
+{
+	fid_t fid;
+
+	fid = fibril_create(program_run_fibril, NULL);
+	if (fid == 0) {
+		printf("Error creating fibril\n");
+		exit(1);
+	}
+
+	fibril_add_ready(fid);
+}
+
+static int program_run_fibril(void *arg)
+{
+	int rc;
+
+	/*
+	 * This must be done in background as it will block until
+	 * we let the task reply to this call.
+	 */
+	rc = loader_run(task_ldr);
+	if (rc != 0) {
+		printf("Error running program\n");
+		exit(1);
+	}
+
+	free(task_ldr);
+	task_ldr = NULL;
+
+	printf("program_run_fibril exiting\n");
+	return 0;
+}
+
+
+static int connect_task(task_id_t task_id)
 {
 	int rc;
@@ -149,4 +188,5 @@
 
 	case V_HASH:
+	case V_PTR:
 		printf("0x%08lx", val);
 		break;
@@ -469,17 +509,50 @@
 }
 
-static void trace_active_task(task_id_t task_id)
+static loader_t *preload_task(const char *path, char *const argv[],
+    task_id_t *task_id)
+{
+	loader_t *ldr;
+	int rc;
+
+	/* Spawn a program loader */	
+	ldr = loader_spawn();
+	if (ldr == NULL)
+		return 0;
+
+	/* Get task ID. */
+	rc = loader_get_task_id(ldr, task_id);
+	if (rc != EOK)
+		goto error;
+
+	/* Send program pathname */
+	rc = loader_set_pathname(ldr, path);
+	if (rc != EOK)
+		goto error;
+
+	/* Send arguments */
+	rc = loader_set_args(ldr, argv);
+	if (rc != EOK)
+		goto error;
+
+	/* Load the program. */
+	rc = loader_load_program(ldr);
+	if (rc != EOK)
+		goto error;
+
+	/* Success */
+	return ldr;
+
+	/* Error exit */
+error:
+	loader_abort(ldr);
+	free(ldr);
+	return NULL;
+}
+
+static void trace_task(task_id_t task_id)
 {
 	int i;
 	int rc;
 	int c;
-
-	rc = task_connect(task_id);
-	if (rc < 0) {
-		printf("Failed to connect to task %lld\n", task_id);
-		return;
-	}
-
-	printf("Connected to task %lld\n", task_id);
 
 	ipcp_init();
@@ -657,4 +730,5 @@
 				--argc; ++argv;
 				task_id = strtol(*argv, &err_p, 10);
+				task_ldr = NULL;
 				if (*err_p) {
 					printf("Task ID syntax error\n");
@@ -687,5 +761,5 @@
 	}
 
-	/* Execute the specified command and trace the new task. */
+	/* Preload the specified program file. */
 	printf("Spawning '%s' with arguments:\n", *argv);
 	{
@@ -693,5 +767,5 @@
 		while (*cp) printf("'%s'\n", *cp++);
 	}
-	task_id = task_spawn(*argv, argv);
+	task_ldr = preload_task(*argv, argv, &task_id);
 
 	return 0;
@@ -700,4 +774,6 @@
 int main(int argc, char *argv[])
 {
+	int rc;
+
 	printf("System Call / IPC Tracer\n");
 
@@ -708,5 +784,18 @@
 
 	main_init();
-	trace_active_task(task_id);
+
+	rc = connect_task(task_id);
+	if (rc < 0) {
+		printf("Failed connecting to task %lld\n", task_id);
+		return 1;
+	}
+
+	printf("Connected to task %lld\n", task_id);
+
+	if (task_ldr != NULL) {
+		program_run();
+	}
+
+	trace_task(task_id);
 
 	return 0;
Index: uspace/lib/libc/generic/loader.c
===================================================================
--- uspace/lib/libc/generic/loader.c	(revision 45454e9b4eae43c54f3381318875dcf28b2419a0)
+++ uspace/lib/libc/generic/loader.c	(revision 4470e2627030413dc38c0d3b98d9c6a3e1672564)
@@ -206,5 +206,28 @@
 }
 
+/** Instruct loader to load the program.
+ *
+ * If this function succeeds, the program has been successfully loaded
+ * and is ready to be executed.
+ *
+ * @param ldr		Loader connection structure.
+ * @return		Zero on success or negative error code.
+ */
+int loader_load_program(loader_t *ldr)
+{
+	int rc;
+
+	rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
 /** Instruct loader to execute the program.
+ *
+ * Note that this function blocks until the loader actually replies
+ * so you cannot expect this function to return if you are debugging
+ * the task and its thread is stopped.
  *
  * After using this function, no further operations must be performed
@@ -214,5 +237,5 @@
  * @return		Zero on success or negative error code.
  */
-int loader_start_program(loader_t *ldr)
+int loader_run(loader_t *ldr)
 {
 	int rc;
@@ -222,5 +245,4 @@
 		return rc;
 
-	ipc_hangup(ldr->phone_id);
 	return EOK;
 }
Index: uspace/lib/libc/generic/task.c
===================================================================
--- uspace/lib/libc/generic/task.c	(revision 45454e9b4eae43c54f3381318875dcf28b2419a0)
+++ uspace/lib/libc/generic/task.c	(revision 4470e2627030413dc38c0d3b98d9c6a3e1672564)
@@ -64,5 +64,5 @@
 	int rc;
 
-	/* Spawn a program loader */	
+	/* Spawn a program loader. */	
 	ldr = loader_spawn();
 	if (ldr == NULL)
@@ -74,20 +74,28 @@
 		goto error;
 
-	/* Send program pathname */
+	/* Send program pathname. */
 	rc = loader_set_pathname(ldr, path);
 	if (rc != EOK)
 		goto error;
 
-	/* Send arguments */
+	/* Send arguments. */
 	rc = loader_set_args(ldr, argv);
 	if (rc != EOK)
 		goto error;
 
-	/* Request loader to start the program */	
-	rc = loader_start_program(ldr);
+	/* Load the program. */
+	rc = loader_load_program(ldr);
+	if (rc != EOK)
+		goto error;
+
+	/* Run it. */
+	/* Load the program. */
+	rc = loader_run(ldr);
 	if (rc != EOK)
 		goto error;
 
 	/* Success */
+
+	free(ldr);
 	return task_id;
 
@@ -95,4 +103,6 @@
 error:
 	loader_abort(ldr);
+	free(ldr);
+
 	return 0;
 }
Index: uspace/lib/libc/include/ipc/loader.h
===================================================================
--- uspace/lib/libc/include/ipc/loader.h	(revision 45454e9b4eae43c54f3381318875dcf28b2419a0)
+++ uspace/lib/libc/include/ipc/loader.h	(revision 4470e2627030413dc38c0d3b98d9c6a3e1672564)
@@ -43,4 +43,5 @@
 	LOADER_SET_PATHNAME,
 	LOADER_SET_ARGS,
+	LOADER_LOAD,
 	LOADER_RUN
 } fb_request_t;
Index: uspace/lib/libc/include/loader/loader.h
===================================================================
--- uspace/lib/libc/include/loader/loader.h	(revision 45454e9b4eae43c54f3381318875dcf28b2419a0)
+++ uspace/lib/libc/include/loader/loader.h	(revision 4470e2627030413dc38c0d3b98d9c6a3e1672564)
@@ -47,5 +47,6 @@
 extern int loader_set_pathname(loader_t *, const char *);
 extern int loader_set_args(loader_t *, char *const []);
-extern int loader_start_program(loader_t *);
+extern int loader_load_program(loader_t *);
+extern int loader_run(loader_t *);
 extern void loader_abort(loader_t *);
 
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 45454e9b4eae43c54f3381318875dcf28b2419a0)
+++ uspace/srv/loader/main.c	(revision 4470e2627030413dc38c0d3b98d9c6a3e1672564)
@@ -47,4 +47,5 @@
 #include <stdlib.h>
 #include <unistd.h>
+#include <bool.h>
 #include <fcntl.h>
 #include <sys/types.h>
@@ -78,5 +79,11 @@
 static char *arg_buf = NULL;
 
-static int loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
+static elf_info_t prog_info;
+static elf_info_t interp_info;
+
+static bool is_dyn_linked;
+
+
+static void loader_get_taskid(ipc_callid_t rid, ipc_call_t *request)
 {
 	ipc_callid_t callid;
@@ -213,6 +220,5 @@
 }
 
-
-/** Load and run the previously selected program.
+/** Load the previously selected program.
  *
  * @param rid
@@ -220,10 +226,7 @@
  * @return 0 on success, !0 on error.
  */
-static int loader_run(ipc_callid_t rid, ipc_call_t *request)
+static int loader_load(ipc_callid_t rid, ipc_call_t *request)
 {
 	int rc;
-
-	elf_info_t prog_info;
-	elf_info_t interp_info;
 
 //	printf("Load program '%s'\n", pathname);
@@ -246,7 +249,6 @@
 //		printf("Run statically linked program\n");
 //		printf("entry point: 0x%llx\n", prog_info.entry);
+		is_dyn_linked = false;
 		ipc_answer_0(rid, EOK);
-		close_console();
-		elf_run(&prog_info, &pcb);
 		return 0;
 	}
@@ -266,13 +268,36 @@
 	pcb.rtld_bias = RTLD_BIAS;
 
-	printf("run dynamic linker\n");
-	printf("entry point: 0x%llx\n", interp_info.entry);
-	close_console();
-
+	is_dyn_linked = true;
 	ipc_answer_0(rid, EOK);
-	elf_run(&interp_info, &pcb);
+
+	return 0;
+}
+
+
+/** Run the previously loaded program.
+ *
+ * @param rid
+ * @param request
+ * @return 0 on success, !0 on error.
+ */
+static void loader_run(ipc_callid_t rid, ipc_call_t *request)
+{
+	if (is_dyn_linked == true) {
+		/* Dynamically linked program */
+		printf("run dynamic linker\n");
+		printf("entry point: 0x%llx\n", interp_info.entry);
+		close_console();
+
+		ipc_answer_0(rid, EOK);
+		elf_run(&interp_info, &pcb);
+
+	} else {
+		/* Statically linked program */
+		close_console();
+		ipc_answer_0(rid, EOK);
+		elf_run(&prog_info, &pcb);
+	} 
 
 	/* Not reached */
-	return 0;
 }
 
@@ -293,6 +318,5 @@
 	while (1) {
 		callid = async_get_call(&call);
-//		printf("received call from phone %d, method=%d\n",
-//			call.in_phone_hash, IPC_GET_METHOD(call));
+
 		switch (IPC_GET_METHOD(call)) {
 		case LOADER_GET_TASKID:
@@ -304,8 +328,11 @@
 		case LOADER_SET_ARGS:
 			loader_set_args(callid, &call);
+			continue;
+		case LOADER_LOAD:
+			loader_load(callid, &call);
+			continue;
 		case LOADER_RUN:
 			loader_run(callid, &call);
-			exit(0);
-			continue;
+			/* Not reached */
 		default:
 			retval = ENOENT;
