00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <unistd.h>
00049 #include <bool.h>
00050 #include <fcntl.h>
00051 #include <sys/types.h>
00052 #include <ipc/services.h>
00053 #include <ipc/loader.h>
00054 #include <ipc/ns.h>
00055 #include <macros.h>
00056 #include <loader/pcb.h>
00057 #include <entry_point.h>
00058 #include <errno.h>
00059 #include <async.h>
00060 #include <str.h>
00061 #include <as.h>
00062
00063 #include <elf.h>
00064 #include <elf_load.h>
00065
00066 #ifdef CONFIG_RTLD
00067 #include <rtld/rtld.h>
00068 #include <rtld/dynamic.h>
00069 #include <rtld/module.h>
00070
00071 static int ldr_load_dyn_linked(elf_info_t *p_info);
00072 #endif
00073
00074 #define DPRINTF(...)
00075
00077 static char *pathname = NULL;
00078
00080 static pcb_t pcb;
00081
00083 static char *cwd = NULL;
00084
00086 static int argc = 0;
00088 static char **argv = NULL;
00090 static char *arg_buf = NULL;
00091
00093 static int filc = 0;
00095 static fdi_node_t **filv = NULL;
00097 static fdi_node_t *fil_buf = NULL;
00098
00099 static elf_info_t prog_info;
00100
00102 static bool connected = false;
00103
00104 #ifdef CONFIG_RTLD
00105
00106 runtime_env_t dload_re;
00107 static module_t prog_mod;
00108 #endif
00109
00110 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
00111 {
00112 ipc_callid_t callid;
00113 task_id_t task_id;
00114 size_t len;
00115
00116 task_id = task_get_id();
00117
00118 if (!async_data_read_receive(&callid, &len)) {
00119 async_answer_0(callid, EINVAL);
00120 async_answer_0(rid, EINVAL);
00121 return;
00122 }
00123
00124 if (len > sizeof(task_id))
00125 len = sizeof(task_id);
00126
00127 async_data_read_finalize(callid, &task_id, len);
00128 async_answer_0(rid, EOK);
00129 }
00130
00136 static void ldr_set_cwd(ipc_callid_t rid, ipc_call_t *request)
00137 {
00138 char *buf;
00139 int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
00140
00141 if (rc == EOK) {
00142 if (cwd != NULL)
00143 free(cwd);
00144
00145 cwd = buf;
00146 }
00147
00148 async_answer_0(rid, rc);
00149 }
00150
00156 static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
00157 {
00158 char *buf;
00159 int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
00160
00161 if (rc == EOK) {
00162 if (pathname != NULL)
00163 free(pathname);
00164
00165 pathname = buf;
00166 }
00167
00168 async_answer_0(rid, rc);
00169 }
00170
00176 static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
00177 {
00178 char *buf;
00179 size_t buf_size;
00180 int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, &buf_size);
00181
00182 if (rc == EOK) {
00183
00184
00185
00186 char *cur = buf;
00187 int count = 0;
00188
00189 while (cur < buf + buf_size) {
00190 size_t arg_size = str_size(cur);
00191 cur += arg_size + 1;
00192 count++;
00193 }
00194
00195
00196
00197
00198 char **_argv = (char **) malloc((count + 1) * sizeof(char *));
00199 if (_argv == NULL) {
00200 free(buf);
00201 async_answer_0(rid, ENOMEM);
00202 return;
00203 }
00204
00205
00206
00207
00208 cur = buf;
00209 count = 0;
00210 while (cur < buf + buf_size) {
00211 _argv[count] = cur;
00212
00213 size_t arg_size = str_size(cur);
00214 cur += arg_size + 1;
00215 count++;
00216 }
00217 _argv[count] = NULL;
00218
00219
00220
00221
00222 if (arg_buf != NULL)
00223 free(arg_buf);
00224
00225 if (argv != NULL)
00226 free(argv);
00227
00228 argc = count;
00229 arg_buf = buf;
00230 argv = _argv;
00231 }
00232
00233 async_answer_0(rid, rc);
00234 }
00235
00241 static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
00242 {
00243 fdi_node_t *buf;
00244 size_t buf_size;
00245 int rc = async_data_write_accept((void **) &buf, false, 0, 0,
00246 sizeof(fdi_node_t), &buf_size);
00247
00248 if (rc == EOK) {
00249 int count = buf_size / sizeof(fdi_node_t);
00250
00251
00252
00253
00254 fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *));
00255 if (_filv == NULL) {
00256 free(buf);
00257 async_answer_0(rid, ENOMEM);
00258 return;
00259 }
00260
00261
00262
00263
00264 int i;
00265 for (i = 0; i < count; i++)
00266 _filv[i] = &buf[i];
00267
00268 _filv[count] = NULL;
00269
00270
00271
00272
00273 if (fil_buf != NULL)
00274 free(fil_buf);
00275
00276 if (filv != NULL)
00277 free(filv);
00278
00279 filc = count;
00280 fil_buf = buf;
00281 filv = _filv;
00282 }
00283
00284 async_answer_0(rid, EOK);
00285 }
00286
00293 static int ldr_load(ipc_callid_t rid, ipc_call_t *request)
00294 {
00295 int rc;
00296
00297 rc = elf_load_file(pathname, 0, 0, &prog_info);
00298 if (rc != EE_OK) {
00299 DPRINTF("Failed to load executable '%s'.\n", pathname);
00300 async_answer_0(rid, EINVAL);
00301 return 1;
00302 }
00303
00304 elf_create_pcb(&prog_info, &pcb);
00305
00306 pcb.cwd = cwd;
00307
00308 pcb.argc = argc;
00309 pcb.argv = argv;
00310
00311 pcb.filc = filc;
00312 pcb.filv = filv;
00313
00314 if (prog_info.interp == NULL) {
00315
00316 async_answer_0(rid, EOK);
00317 return 0;
00318 }
00319
00320 DPRINTF("Binary is dynamically linked.\n");
00321 #ifdef CONFIG_RTLD
00322 DPRINTF(" - pcb address: %p\n", &pcb);
00323 DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
00324
00325 rc = ldr_load_dyn_linked(&prog_info);
00326 #else
00327 rc = ENOTSUP;
00328 #endif
00329 async_answer_0(rid, rc);
00330 return 0;
00331 }
00332
00333 #ifdef CONFIG_RTLD
00334
00335 static int ldr_load_dyn_linked(elf_info_t *p_info)
00336 {
00337 runtime_env = &dload_re;
00338
00339 DPRINTF("Load dynamically linked program.\n");
00340
00341
00342
00343
00344
00345
00346 DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
00347 dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
00348 prog_mod.bias = 0;
00349 prog_mod.dyn.soname = "[program]";
00350
00351
00352 list_initialize(&runtime_env->modules_head);
00353 list_append(&prog_mod.modules_link, &runtime_env->modules_head);
00354
00355
00356 runtime_env->program = &prog_mod;
00357
00358
00359 runtime_env->next_bias = 0x1000000;
00360
00361
00362
00363
00364
00365 DPRINTF("Load all program dependencies\n");
00366 module_load_deps(&prog_mod);
00367
00368
00369
00370
00371
00372
00373 DPRINTF("Relocate all modules\n");
00374 modules_process_relocs(&prog_mod);
00375
00376
00377 pcb.rtld_runtime = (void *) runtime_env;
00378
00379 return 0;
00380 }
00381 #endif
00382
00389 static void ldr_run(ipc_callid_t rid, ipc_call_t *request)
00390 {
00391 const char *cp;
00392
00393 DPRINTF("Set task name\n");
00394
00395
00396 cp = str_rchr(pathname, '/');
00397 cp = (cp == NULL) ? pathname : (cp + 1);
00398 task_set_name(cp);
00399
00400
00401 DPRINTF("Reply OK\n");
00402 async_answer_0(rid, EOK);
00403 DPRINTF("Jump to entry point at %p\n", pcb.entry);
00404 entry_point_jmp(prog_info.entry, &pcb);
00405
00406
00407 }
00408
00414 static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
00415 {
00416 ipc_callid_t callid;
00417 ipc_call_t call;
00418 int retval;
00419
00420
00421 if (connected) {
00422 async_answer_0(iid, ELIMIT);
00423 return;
00424 }
00425
00426 connected = true;
00427
00428
00429 async_answer_0(iid, EOK);
00430
00431
00432 (void) iid;
00433 (void) icall;
00434
00435 while (1) {
00436 callid = async_get_call(&call);
00437
00438 switch (IPC_GET_IMETHOD(call)) {
00439 case IPC_M_PHONE_HUNGUP:
00440 exit(0);
00441 case LOADER_GET_TASKID:
00442 ldr_get_taskid(callid, &call);
00443 continue;
00444 case LOADER_SET_CWD:
00445 ldr_set_cwd(callid, &call);
00446 continue;
00447 case LOADER_SET_PATHNAME:
00448 ldr_set_pathname(callid, &call);
00449 continue;
00450 case LOADER_SET_ARGS:
00451 ldr_set_args(callid, &call);
00452 continue;
00453 case LOADER_SET_FILES:
00454 ldr_set_files(callid, &call);
00455 continue;
00456 case LOADER_LOAD:
00457 ldr_load(callid, &call);
00458 continue;
00459 case LOADER_RUN:
00460 ldr_run(callid, &call);
00461
00462 default:
00463 retval = EINVAL;
00464 break;
00465 }
00466
00467 if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP)
00468 async_answer_0(callid, retval);
00469 }
00470 }
00471
00474 int main(int argc, char *argv[])
00475 {
00476
00477 async_set_client_connection(ldr_connection);
00478
00479
00480 task_id_t id = task_get_id();
00481 int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
00482 if (rc != EOK)
00483 return -1;
00484
00485
00486 if (service_register(SERVICE_LOAD) != EOK)
00487 return -2;
00488
00489 async_manager();
00490
00491
00492 return 0;
00493 }
00494