Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3469 → Rev 3470

/trunk/uspace/app/trace/trace.c
42,6 → 42,7
#include <udebug.h>
#include <async.h>
#include <task.h>
#include <loader/loader.h>
 
// Temporary: service and method names
#include "proto.h"
70,14 → 71,52
 
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;
 
rc = ipc_connect_kbox(task_id);
 
if (rc == ENOTSUP) {
148,6 → 187,7
break;
 
case V_HASH:
case V_PTR:
printf("0x%08lx", val);
break;
 
468,20 → 508,53
fibril_add_ready(fid);
}
 
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();
 
/*
656,6 → 729,7
/* Trace an already running task */
--argc; ++argv;
task_id = strtol(*argv, &err_p, 10);
task_ldr = NULL;
if (*err_p) {
printf("Task ID syntax error\n");
print_syntax();
686,13 → 760,13
return -1;
}
 
/* Execute the specified command and trace the new task. */
/* Preload the specified program file. */
printf("Spawning '%s' with arguments:\n", *argv);
{
char **cp = argv;
while (*cp) printf("'%s'\n", *cp++);
}
task_id = task_spawn(*argv, argv);
task_ldr = preload_task(*argv, argv, &task_id);
 
return 0;
}
699,6 → 773,8
 
int main(int argc, char *argv[])
{
int rc;
 
printf("System Call / IPC Tracer\n");
 
display_mask = DM_THREAD | DM_SYSTEM | DM_USER;
707,8 → 783,21
return 1;
 
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;
}
 
/trunk/uspace/lib/libc/include/loader/loader.h
46,7 → 46,8
extern int loader_get_task_id(loader_t *, task_id_t *);
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 *);
 
#endif
/trunk/uspace/lib/libc/include/ipc/loader.h
42,6 → 42,7
LOADER_GET_TASKID,
LOADER_SET_PATHNAME,
LOADER_SET_ARGS,
LOADER_LOAD,
LOADER_RUN
} fb_request_t;
 
/trunk/uspace/lib/libc/generic/task.c
63,7 → 63,7
task_id_t task_id;
int rc;
 
/* Spawn a program loader */
/* Spawn a program loader. */
ldr = loader_spawn();
if (ldr == NULL)
return 0;
73,27 → 73,37
if (rc != EOK)
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;
 
/* Error exit */
error:
loader_abort(ldr);
free(ldr);
 
return 0;
}
 
/trunk/uspace/lib/libc/generic/loader.c
205,8 → 205,31
return EOK;
}
 
/** 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
* on the loader structure. It should be de-allocated using free().
*
213,7 → 236,7
* @param ldr Loader connection structure.
* @return Zero on success or negative error code.
*/
int loader_start_program(loader_t *ldr)
int loader_run(loader_t *ldr)
{
int rc;
 
221,7 → 244,6
if (rc != EOK)
return rc;
 
ipc_hangup(ldr->phone_id);
return EOK;
}
 
/trunk/uspace/srv/loader/main.c
46,6 → 46,7
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <bool.h>
#include <fcntl.h>
#include <sys/types.h>
#include <ipc/ipc.h>
77,7 → 78,13
/** Buffer holding all arguments */
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;
task_id_t task_id;
212,20 → 219,16
argv[n] = NULL;
}
 
 
/** Load and run the previously selected program.
/** Load the previously selected program.
*
* @param rid
* @param request
* @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);
 
rc = elf_load_file(pathname, 0, &prog_info);
245,9 → 248,8
/* Statically linked program */
// 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;
}
 
265,17 → 267,40
pcb.rtld_dynamic = interp_info.dynamic;
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);
 
/* Not reached */
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 */
}
 
/** Handle loader connection.
*
* Receive and carry out commands (of which the last one should be
292,8 → 317,7
 
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:
loader_get_taskid(callid, &call);
303,10 → 327,13
continue;
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;
break;