Changeset eb522e8 in mainline for uspace/srv/loader/main.c


Ignore:
Timestamp:
2011-06-01T08:43:42Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8d6c1f1
Parents:
9e2e715 (diff), e51a514 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Huuuuuge merge from development - all the work actually :)

File:
1 edited

Legend:

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

    r9e2e715 reb522e8  
    5050#include <fcntl.h>
    5151#include <sys/types.h>
    52 #include <ipc/ipc.h>
    5352#include <ipc/services.h>
    5453#include <ipc/loader.h>
     
    5655#include <macros.h>
    5756#include <loader/pcb.h>
     57#include <entry_point.h>
    5858#include <errno.h>
    5959#include <async.h>
     
    6363#include <elf.h>
    6464#include <elf_load.h>
     65
     66#ifdef CONFIG_RTLD
     67#include <rtld/rtld.h>
     68#include <rtld/dynamic.h>
     69#include <rtld/module.h>
     70
     71static int ldr_load_dyn_linked(elf_info_t *p_info);
     72#endif
    6573
    6674#define DPRINTF(...)
     
    9098
    9199static elf_info_t prog_info;
    92 static elf_info_t interp_info;
    93 
    94 static bool is_dyn_linked;
    95100
    96101/** Used to limit number of connections to one. */
    97 static bool connected;
     102static bool connected = false;
     103
     104#ifdef CONFIG_RTLD
     105/** State structure of the dynamic linker. */
     106runtime_env_t dload_re;
     107static module_t prog_mod;
     108#endif
    98109
    99110static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
     
    106117       
    107118        if (!async_data_read_receive(&callid, &len)) {
    108                 ipc_answer_0(callid, EINVAL);
    109                 ipc_answer_0(rid, EINVAL);
     119                async_answer_0(callid, EINVAL);
     120                async_answer_0(rid, EINVAL);
    110121                return;
    111122        }
     
    115126       
    116127        async_data_read_finalize(callid, &task_id, len);
    117         ipc_answer_0(rid, EOK);
     128        async_answer_0(rid, EOK);
    118129}
    119130
     
    135146        }
    136147       
    137         ipc_answer_0(rid, rc);
     148        async_answer_0(rid, rc);
    138149}
    139150
     
    155166        }
    156167       
    157         ipc_answer_0(rid, rc);
     168        async_answer_0(rid, rc);
    158169}
    159170
     
    188199                if (_argv == NULL) {
    189200                        free(buf);
    190                         ipc_answer_0(rid, ENOMEM);
     201                        async_answer_0(rid, ENOMEM);
    191202                        return;
    192203                }
     
    220231        }
    221232       
    222         ipc_answer_0(rid, rc);
     233        async_answer_0(rid, rc);
    223234}
    224235
     
    244255                if (_filv == NULL) {
    245256                        free(buf);
    246                         ipc_answer_0(rid, ENOMEM);
     257                        async_answer_0(rid, ENOMEM);
    247258                        return;
    248259                }
     
    271282        }
    272283       
    273         ipc_answer_0(rid, EOK);
     284        async_answer_0(rid, EOK);
    274285}
    275286
     
    284295        int rc;
    285296       
    286         rc = elf_load_file(pathname, 0, &prog_info);
     297        rc = elf_load_file(pathname, 0, 0, &prog_info);
    287298        if (rc != EE_OK) {
    288299                DPRINTF("Failed to load executable '%s'.\n", pathname);
    289                 ipc_answer_0(rid, EINVAL);
     300                async_answer_0(rid, EINVAL);
    290301                return 1;
    291302        }
     
    303314        if (prog_info.interp == NULL) {
    304315                /* Statically linked program */
    305                 is_dyn_linked = false;
    306                 ipc_answer_0(rid, EOK);
     316                async_answer_0(rid, EOK);
    307317                return 0;
    308318        }
    309319       
    310         rc = elf_load_file(prog_info.interp, 0, &interp_info);
    311         if (rc != EE_OK) {
    312                 DPRINTF("Failed to load interpreter '%s.'\n",
    313                     prog_info.interp);
    314                 ipc_answer_0(rid, EINVAL);
    315                 return 1;
    316         }
    317        
    318         is_dyn_linked = true;
    319         ipc_answer_0(rid, EOK);
    320        
     320        DPRINTF("Binary is dynamically linked.\n");
     321#ifdef CONFIG_RTLD
     322        DPRINTF(" - pcb address: %p\n", &pcb);
     323        DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
     324
     325        rc = ldr_load_dyn_linked(&prog_info);
     326#else
     327        rc = ENOTSUP;
     328#endif
     329        async_answer_0(rid, rc);
    321330        return 0;
    322331}
    323332
     333#ifdef CONFIG_RTLD
     334
     335static int ldr_load_dyn_linked(elf_info_t *p_info)
     336{
     337        runtime_env = &dload_re;
     338
     339        DPRINTF("Load dynamically linked program.\n");
     340
     341        /*
     342         * First we need to process dynamic sections of the executable
     343         * program and insert it into the module graph.
     344         */
     345
     346        DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
     347        dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
     348        prog_mod.bias = 0;
     349        prog_mod.dyn.soname = "[program]";
     350
     351        /* Initialize list of loaded modules */
     352        list_initialize(&runtime_env->modules_head);
     353        list_append(&prog_mod.modules_link, &runtime_env->modules_head);
     354
     355        /* Pointer to program module. Used as root of the module graph. */
     356        runtime_env->program = &prog_mod;
     357
     358        /* Work around non-existent memory space allocation. */
     359        runtime_env->next_bias = 0x1000000;
     360
     361        /*
     362         * Now we can continue with loading all other modules.
     363         */
     364
     365        DPRINTF("Load all program dependencies\n");
     366        module_load_deps(&prog_mod);
     367
     368        /*
     369         * Now relocate/link all modules together.
     370         */
     371
     372        /* Process relocations in all modules */
     373        DPRINTF("Relocate all modules\n");
     374        modules_process_relocs(&prog_mod);
     375
     376        /* Pass runtime evironment pointer through PCB. */
     377        pcb.rtld_runtime = (void *) runtime_env;
     378
     379        return 0;
     380}
     381#endif
    324382
    325383/** Run the previously loaded program.
     
    333391        const char *cp;
    334392       
     393        DPRINTF("Set task name\n");
     394
    335395        /* Set the task name. */
    336396        cp = str_rchr(pathname, '/');
     
    338398        task_set_name(cp);
    339399       
    340         if (is_dyn_linked == true) {
    341                 /* Dynamically linked program */
    342                 DPRINTF("Run ELF interpreter.\n");
    343                 DPRINTF("Entry point: %p\n", interp_info.entry);
    344                
    345                 ipc_answer_0(rid, EOK);
    346                 elf_run(&interp_info, &pcb);
    347         } else {
    348                 /* Statically linked program */
    349                 ipc_answer_0(rid, EOK);
    350                 elf_run(&prog_info, &pcb);
    351         }
     400        /* Run program */
     401        DPRINTF("Reply OK\n");
     402        async_answer_0(rid, EOK);
     403        DPRINTF("Jump to entry point at %p\n", pcb.entry);
     404        entry_point_jmp(prog_info.entry, &pcb);
    352405       
    353406        /* Not reached */
     
    367420        /* Already have a connection? */
    368421        if (connected) {
    369                 ipc_answer_0(iid, ELIMIT);
     422                async_answer_0(iid, ELIMIT);
    370423                return;
    371424        }
     
    374427       
    375428        /* Accept the connection */
    376         ipc_answer_0(iid, EOK);
     429        async_answer_0(iid, EOK);
    377430       
    378431        /* Ignore parameters, the connection is already open */
     
    383436                callid = async_get_call(&call);
    384437               
    385                 switch (IPC_GET_METHOD(call)) {
     438                switch (IPC_GET_IMETHOD(call)) {
    386439                case IPC_M_PHONE_HUNGUP:
    387440                        exit(0);
     
    408461                        /* Not reached */
    409462                default:
    410                         retval = ENOENT;
     463                        retval = EINVAL;
    411464                        break;
    412465                }
    413                 if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
    414                     IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
    415                         DPRINTF("Responding EINVAL to method %d.\n",
    416                             IPC_GET_METHOD(call));
    417                         ipc_answer_0(callid, EINVAL);
    418                 }
     466               
     467                if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP)
     468                        async_answer_0(callid, retval);
    419469        }
    420470}
     
    424474int main(int argc, char *argv[])
    425475{
    426         ipcarg_t phonead;
    427         task_id_t id;
    428         int rc;
    429 
    430         connected = false;
    431 
     476        /* Set a handler of incomming connections. */
     477        async_set_client_connection(ldr_connection);
     478       
    432479        /* Introduce this task to the NS (give it our task ID). */
    433         id = task_get_id();
    434         rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
     480        task_id_t id = task_get_id();
     481        int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
    435482        if (rc != EOK)
    436483                return -1;
    437 
    438         /* Set a handler of incomming connections. */
    439         async_set_client_connection(ldr_connection);
    440484       
    441485        /* Register at naming service. */
    442         if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
     486        if (service_register(SERVICE_LOAD) != EOK)
    443487                return -2;
    444 
     488       
    445489        async_manager();
    446490       
Note: See TracChangeset for help on using the changeset viewer.