Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/loader/main.c

    rffa2c8ef r27b76ca  
    5252#include <ipc/services.h>
    5353#include <ipc/loader.h>
    54 #include <ipc/ns.h>
    55 #include <macros.h>
     54#include <ns.h>
    5655#include <loader/pcb.h>
     56#include <entry_point.h>
    5757#include <errno.h>
    5858#include <async.h>
    5959#include <str.h>
    6060#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
     70static int ldr_load_dyn_linked(elf_info_t *p_info);
     71#endif
    6472
    6573#define DPRINTF(...)
     
    8290
    8391/** 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;
     92static unsigned int filc = 0;
    8993
    9094static elf_info_t prog_info;
    91 static elf_info_t interp_info;
    92 
    93 static bool is_dyn_linked;
    9495
    9596/** Used to limit number of connections to one. */
    9697static bool connected = false;
     98
     99#ifdef CONFIG_RTLD
     100/** State structure of the dynamic linker. */
     101runtime_env_t dload_re;
     102static module_t prog_mod;
     103#endif
    97104
    98105static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
     
    229236static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
    230237{
    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;
    247249                }
    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
    272257        async_answer_0(rid, EOK);
    273258}
     
    283268        int rc;
    284269       
    285         rc = elf_load_file(pathname, 0, &prog_info);
     270        rc = elf_load_file(pathname, 0, 0, &prog_info);
    286271        if (rc != EE_OK) {
    287272                DPRINTF("Failed to load executable '%s'.\n", pathname);
     
    298283       
    299284        pcb.filc = filc;
    300         pcb.filv = filv;
    301285       
    302286        if (prog_info.interp == NULL) {
    303287                /* Statically linked program */
    304                 is_dyn_linked = false;
    305288                async_answer_0(rid, EOK);
    306289                return 0;
    307290        }
    308291       
    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);
    320302        return 0;
    321303}
    322304
     305#ifdef CONFIG_RTLD
     306
     307static 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
    323354
    324355/** Run the previously loaded program.
     
    332363        const char *cp;
    333364       
     365        DPRINTF("Set task name\n");
     366
    334367        /* Set the task name. */
    335368        cp = str_rchr(pathname, '/');
     
    337370        task_set_name(cp);
    338371       
    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);
    351377       
    352378        /* Not reached */
     
    358384 * to execute the loaded program).
    359385 */
    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        
     386static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     387{
    366388        /* Already have a connection? */
    367389        if (connected) {
     
    376398       
    377399        /* Ignore parameters, the connection is already open */
    378         (void) iid;
    379400        (void) icall;
    380401       
    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);
    383409               
    384410                switch (IPC_GET_IMETHOD(call)) {
    385                 case IPC_M_PHONE_HUNGUP:
    386                         exit(0);
    387411                case LOADER_GET_TASKID:
    388412                        ldr_get_taskid(callid, &call);
     
    407431                        /* Not reached */
    408432                default:
    409                         retval = ENOENT;
     433                        retval = EINVAL;
    410434                        break;
    411435                }
    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);
    417438        }
    418439}
     
    427448        /* Introduce this task to the NS (give it our task ID). */
    428449        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);
    430451        if (rc != EOK)
    431452                return -1;
Note: See TracChangeset for help on using the changeset viewer.