Changes in uspace/srv/loader/main.c [ffa2c8ef:27b76ca] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/loader/main.c
rffa2c8ef r27b76ca 52 52 #include <ipc/services.h> 53 53 #include <ipc/loader.h> 54 #include <ipc/ns.h> 55 #include <macros.h> 54 #include <ns.h> 56 55 #include <loader/pcb.h> 56 #include <entry_point.h> 57 57 #include <errno.h> 58 58 #include <async.h> 59 59 #include <str.h> 60 60 #include <as.h> 61 62 #include <elf.h> 63 #include <elf_load.h> 61 #include <elf/elf.h> 62 #include <elf/elf_load.h> 63 #include <vfs/vfs.h> 64 65 #ifdef CONFIG_RTLD 66 #include <rtld/rtld.h> 67 #include <rtld/dynamic.h> 68 #include <rtld/module.h> 69 70 static int ldr_load_dyn_linked(elf_info_t *p_info); 71 #endif 64 72 65 73 #define DPRINTF(...) … … 82 90 83 91 /** Number of preset files */ 84 static int filc = 0; 85 /** Preset files vector */ 86 static fdi_node_t **filv = NULL; 87 /** Buffer holding all preset files */ 88 static fdi_node_t *fil_buf = NULL; 92 static unsigned int filc = 0; 89 93 90 94 static elf_info_t prog_info; 91 static elf_info_t interp_info;92 93 static bool is_dyn_linked;94 95 95 96 /** Used to limit number of connections to one. */ 96 97 static bool connected = false; 98 99 #ifdef CONFIG_RTLD 100 /** State structure of the dynamic linker. */ 101 runtime_env_t dload_re; 102 static module_t prog_mod; 103 #endif 97 104 98 105 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request) … … 229 236 static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request) 230 237 { 231 fdi_node_t *buf; 232 size_t buf_size; 233 int rc = async_data_write_accept((void **) &buf, false, 0, 0, 234 sizeof(fdi_node_t), &buf_size); 235 236 if (rc == EOK) { 237 int count = buf_size / sizeof(fdi_node_t); 238 239 /* 240 * Allocate new filv 241 */ 242 fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *)); 243 if (_filv == NULL) { 244 free(buf); 245 async_answer_0(rid, ENOMEM); 246 return; 238 size_t count = IPC_GET_ARG1(*request); 239 240 async_exch_t *vfs_exch = vfs_exchange_begin(); 241 242 for (filc = 0; filc < count; filc++) { 243 ipc_callid_t callid; 244 int fd; 245 246 if (!async_state_change_receive(&callid, NULL, NULL, NULL)) { 247 async_answer_0(callid, EINVAL); 248 break; 247 249 } 248 249 /* 250 * Fill the new filv with argument pointers 251 */ 252 int i; 253 for (i = 0; i < count; i++) 254 _filv[i] = &buf[i]; 255 256 _filv[count] = NULL; 257 258 /* 259 * Copy temporary data to global variables 260 */ 261 if (fil_buf != NULL) 262 free(fil_buf); 263 264 if (filv != NULL) 265 free(filv); 266 267 filc = count; 268 fil_buf = buf; 269 filv = _filv; 270 } 271 250 async_state_change_finalize(callid, vfs_exch); 251 fd = fd_wait(); 252 assert(fd == (int) filc); 253 } 254 255 vfs_exchange_end(vfs_exch); 256 272 257 async_answer_0(rid, EOK); 273 258 } … … 283 268 int rc; 284 269 285 rc = elf_load_file(pathname, 0, &prog_info);270 rc = elf_load_file(pathname, 0, 0, &prog_info); 286 271 if (rc != EE_OK) { 287 272 DPRINTF("Failed to load executable '%s'.\n", pathname); … … 298 283 299 284 pcb.filc = filc; 300 pcb.filv = filv;301 285 302 286 if (prog_info.interp == NULL) { 303 287 /* Statically linked program */ 304 is_dyn_linked = false;305 288 async_answer_0(rid, EOK); 306 289 return 0; 307 290 } 308 291 309 rc = elf_load_file(prog_info.interp, 0, &interp_info); 310 if (rc != EE_OK) { 311 DPRINTF("Failed to load interpreter '%s.'\n", 312 prog_info.interp); 313 async_answer_0(rid, EINVAL); 314 return 1; 315 } 316 317 is_dyn_linked = true; 318 async_answer_0(rid, EOK); 319 292 DPRINTF("Binary is dynamically linked.\n"); 293 #ifdef CONFIG_RTLD 294 DPRINTF(" - pcb address: %p\n", &pcb); 295 DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic); 296 297 rc = ldr_load_dyn_linked(&prog_info); 298 #else 299 rc = ENOTSUP; 300 #endif 301 async_answer_0(rid, rc); 320 302 return 0; 321 303 } 322 304 305 #ifdef CONFIG_RTLD 306 307 static int ldr_load_dyn_linked(elf_info_t *p_info) 308 { 309 runtime_env = &dload_re; 310 311 DPRINTF("Load dynamically linked program.\n"); 312 313 /* 314 * First we need to process dynamic sections of the executable 315 * program and insert it into the module graph. 316 */ 317 318 DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic); 319 dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn); 320 prog_mod.bias = 0; 321 prog_mod.dyn.soname = "[program]"; 322 323 /* Initialize list of loaded modules */ 324 list_initialize(&runtime_env->modules); 325 list_append(&prog_mod.modules_link, &runtime_env->modules); 326 327 /* Pointer to program module. Used as root of the module graph. */ 328 runtime_env->program = &prog_mod; 329 330 /* Work around non-existent memory space allocation. */ 331 runtime_env->next_bias = 0x1000000; 332 333 /* 334 * Now we can continue with loading all other modules. 335 */ 336 337 DPRINTF("Load all program dependencies\n"); 338 module_load_deps(&prog_mod); 339 340 /* 341 * Now relocate/link all modules together. 342 */ 343 344 /* Process relocations in all modules */ 345 DPRINTF("Relocate all modules\n"); 346 modules_process_relocs(&prog_mod); 347 348 /* Pass runtime evironment pointer through PCB. */ 349 pcb.rtld_runtime = (void *) runtime_env; 350 351 return 0; 352 } 353 #endif 323 354 324 355 /** Run the previously loaded program. … … 332 363 const char *cp; 333 364 365 DPRINTF("Set task name\n"); 366 334 367 /* Set the task name. */ 335 368 cp = str_rchr(pathname, '/'); … … 337 370 task_set_name(cp); 338 371 339 if (is_dyn_linked == true) { 340 /* Dynamically linked program */ 341 DPRINTF("Run ELF interpreter.\n"); 342 DPRINTF("Entry point: %p\n", interp_info.entry); 343 344 async_answer_0(rid, EOK); 345 elf_run(&interp_info, &pcb); 346 } else { 347 /* Statically linked program */ 348 async_answer_0(rid, EOK); 349 elf_run(&prog_info, &pcb); 350 } 372 /* Run program */ 373 DPRINTF("Reply OK\n"); 374 async_answer_0(rid, EOK); 375 DPRINTF("Jump to entry point at %p\n", pcb.entry); 376 entry_point_jmp(prog_info.entry, &pcb); 351 377 352 378 /* Not reached */ … … 358 384 * to execute the loaded program). 359 385 */ 360 static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall) 361 { 362 ipc_callid_t callid; 363 ipc_call_t call; 364 int retval; 365 386 static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 387 { 366 388 /* Already have a connection? */ 367 389 if (connected) { … … 376 398 377 399 /* Ignore parameters, the connection is already open */ 378 (void) iid;379 400 (void) icall; 380 401 381 while (1) { 382 callid = async_get_call(&call); 402 while (true) { 403 int retval; 404 ipc_call_t call; 405 ipc_callid_t callid = async_get_call(&call); 406 407 if (!IPC_GET_IMETHOD(call)) 408 exit(0); 383 409 384 410 switch (IPC_GET_IMETHOD(call)) { 385 case IPC_M_PHONE_HUNGUP:386 exit(0);387 411 case LOADER_GET_TASKID: 388 412 ldr_get_taskid(callid, &call); … … 407 431 /* Not reached */ 408 432 default: 409 retval = E NOENT;433 retval = EINVAL; 410 434 break; 411 435 } 412 if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP) { 413 DPRINTF("Responding EINVAL to method %d.\n", 414 IPC_GET_IMETHOD(call)); 415 async_answer_0(callid, EINVAL); 416 } 436 437 async_answer_0(callid, retval); 417 438 } 418 439 } … … 427 448 /* Introduce this task to the NS (give it our task ID). */ 428 449 task_id_t id = task_get_id(); 429 int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));450 int rc = ns_intro(id); 430 451 if (rc != EOK) 431 452 return -1;
Note:
See TracChangeset
for help on using the changeset viewer.