Ejemplo n.º 1
0
void _DkDebugAddMap (struct link_map * map)
{
    const ElfW(Ehdr) * ehdr = (void *) map->l_map_start;
    int shdrsz = sizeof(ElfW(Shdr)) * ehdr->e_shnum;
    ElfW(Shdr) * shdr = NULL;
    ElfW(Phdr) * phdr = (void *) (map->l_map_start + ehdr->e_phoff);
    const ElfW(Phdr) * ph;

    int fd = ocall_open(map->l_name, O_RDONLY, 0);
    if (fd < 0)
        return;

    for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
        if (ph->p_type == PT_LOAD &&
            ehdr->e_shoff >= ph->p_offset &&
            ehdr->e_shoff < ph->p_offset + ph->p_filesz) {
            shdr = (void *) map->l_addr + ph->p_vaddr +
                (ehdr->e_shoff - ph->p_offset);
            break;
        }

    if (!shdr) {
        shdr = __alloca(shdrsz);
        unsigned long s = ALLOC_ALIGNDOWN(ehdr->e_shoff);
        unsigned long e = ALLOC_ALIGNUP(ehdr->e_shoff + shdrsz);
        void * umem;
        ocall_map_untrusted(fd, s, e - s, PROT_READ, &umem);
        memcpy(shdr, umem + ehdr->e_shoff - s, shdrsz);
        ocall_unmap_untrusted(umem, e - s);
    }

    ElfW(Shdr) * shdrend = (void *) shdr + shdrsz;
    int shstroff = shdr[ehdr->e_shstrndx].sh_offset;
    size_t shstrsz = shdr[ehdr->e_shstrndx].sh_size;
    const char * shstrtab = NULL;

    for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
        if (ph->p_type == PT_LOAD &&
            shstroff >= ph->p_offset &&
            shstroff < ph->p_offset + ph->p_filesz) {
            shstrtab = (void *) map->l_addr + ph->p_vaddr +
                (shstroff - ph->p_offset);
            break;
        }

    if (!shstrtab) {
        shstrtab = __alloca(shstrsz);
        unsigned long s = ALLOC_ALIGNDOWN(shstroff);
        unsigned long e = ALLOC_ALIGNUP(shstroff + shstrsz);
        void * umem;
        ocall_map_untrusted(fd, s, e - s, PROT_READ, &umem);
        memcpy((void *) shstrtab, umem + shstroff - s, shstrsz);
        ocall_unmap_untrusted(umem, e - s);
    }

    ocall_close(fd);

    ElfW(Addr) text_addr = 0;
    for (ElfW(Shdr) * s = shdr ; s < shdrend ; s++)
        if (strcmp_static(shstrtab + s->sh_name, ".text")) {
            text_addr = map->l_addr + s->sh_addr;
            break;
        }

    if (!text_addr)
        return;

#define BUFFER_LENGTH 4096

    char buffer[BUFFER_LENGTH], * ptr = buffer;

    snprintf(ptr, BUFFER_LENGTH - (ptr - buffer),
             "add-symbol-file %s 0x%016llx -readnow", map->l_name, text_addr);
    ptr += strlen(ptr);

    for (ElfW(Shdr) * s = shdr ; s < shdrend ; s++) {
        if (!s->sh_name || !s->sh_addr)
            continue;
        if (strcmp_static(shstrtab + s->sh_name, ".text"))
            continue;
        if (s->sh_type == SHT_NULL)
            continue;
        if (strpartcmp_static(shstrtab + s->sh_name, ".debug_"))
            continue;

        snprintf(ptr, BUFFER_LENGTH - (ptr - buffer),
                 " -s %s 0x%016llx", shstrtab + s->sh_name,
                 map->l_addr + s->sh_addr);
        ptr += strlen(ptr);
    }

    ocall_load_debug(buffer);
}
Ejemplo n.º 2
0
void pal_main (PAL_NUM pal_token, void * pal_addr,
               const char * pal_name,
               int argc, const char ** argv, const char ** envp,
               PAL_HANDLE parent_handle,
               PAL_HANDLE thread_handle,
               PAL_HANDLE exec_handle,
               PAL_HANDLE manifest_handle)
{
    int ret;
    bool is_parent = !parent_handle;

#if PROFILING == 1
    __pal_control.host_specific_startup_time =
            _DkSystemTimeQuery() - pal_state.start_time;
#endif

    pal_state.pal_token     = pal_token;
    pal_state.pal_addr      = pal_addr;
    pal_state.parent_handle = parent_handle;
    pal_state.pagesize      = _DkGetPagesize();
    pal_state.alloc_align   = _DkGetAllocationAlignment();
    pal_state.alloc_shift   = pal_state.alloc_align - 1;
    pal_state.alloc_mask    = ~pal_state.alloc_shift;

    init_slab_mgr(pal_state.alloc_align);

    char * exec = NULL, * manifest = NULL;

    if (exec_handle) {
        exec = __alloca(URI_MAX);
        ret = _DkStreamGetName(exec_handle, exec, URI_MAX);
        if (ret < 0)
            init_fail(-ret, "cannot get executable name");
    }

    if (manifest_handle) {
        manifest = __alloca(URI_MAX);
        ret = _DkStreamGetName(manifest_handle, manifest, URI_MAX);
        if (ret < 0)
            init_fail(-ret, "cannot get manifest name");
    } else {
        if (is_parent) {
#if PROFILING == 1
            unsigned long before_find_manifest = _DkSystemTimeQuery();
#endif
            do {
                if (exec_handle) {
                    assert(!!exec);
                    /* try open "<exec>.manifest" */
                    manifest = __alloca(URI_MAX);
                    snprintf(manifest, URI_MAX, "%s.manifest", exec);
                    ret = _DkStreamOpen(&manifest_handle,
                                        manifest,
                                        PAL_ACCESS_RDONLY, 0, 0, 0);
                    if (!ret)
                        break;
                }

                /* try open "file:manifest" */
                manifest = "file:manifest";
                ret = _DkStreamOpen(&manifest_handle,
                                    manifest,
                                    PAL_ACCESS_RDONLY, 0, 0, 0);
                if (!ret)
                    break;

                /* well, there is no manifest file, leave it alone */
                if (!manifest_handle)
                    printf("Can't fine any manifest, will run without one\n");
            } while (0);

#if PROFILING == 1
            pal_state.manifest_loading_time +=
                            _DkSystemTimeQuery() - before_find_manifest;
#endif
        }
    }

    /* load manifest if there is one */
    if (manifest_handle) {
#if PROFILING == 1
        unsigned long before_load_manifest = _DkSystemTimeQuery();
#endif

        PAL_STREAM_ATTR attr;
        ret = _DkStreamAttributesQuerybyHandle(manifest_handle, &attr);
        if (ret < 0)
            init_fail(-ret, "cannot open manifest file");

        void * cfg_addr = NULL;
        int cfg_size = attr.pending_size;

        ret = _DkStreamMap(manifest_handle, &cfg_addr,
                           PAL_PROT_READ, 0,
                           ALLOC_ALIGNUP(cfg_size));
        if (ret < 0)
            init_fail(-ret, "cannot open manifest file");

        struct config_store * root_config = malloc(sizeof(struct config_store));
        root_config->raw_data = cfg_addr;
        root_config->raw_size = cfg_size;
        root_config->malloc = malloc;
        root_config->free = free;

        const char * errstring = NULL;
        if ((ret = read_config(root_config, loader_filter, &errstring)) < 0)
            init_fail(-ret, errstring);

        pal_state.root_config = root_config;

#if PROFILING == 1
        pal_state.manifest_loading_time +=
                        _DkSystemTimeQuery() - before_load_manifest;
#endif
    }

    /* if there is no executable, try to find one in the manifest */
    if (is_parent && !exec_handle) {
        exec = __alloca(URI_MAX);
        assert(!!pal_state.root_config);

        ret = get_config(pal_state.root_config, "loader.exec", exec, URI_MAX);
        if (ret > 0) {
            ret = _DkStreamOpen(&exec_handle, exec, PAL_ACCESS_RDONLY,
                                0, 0, 0);
            if (ret < 0)
                init_fail(-ret, "cannot open executable");

            /* must be a ELF */
            if (check_elf_object(exec_handle) < 0)
                init_fail(PAL_ERROR_INVAL, "executable is not a ELF binary");
        } else {
            exec = NULL;
        }
    }

    if (is_parent && !exec_handle && !manifest_handle) {
        printf("USAGE: %s [executable|manifest] args ...\n", pal_name);
        _DkProcessExit(0);
        return;
    }

    pal_state.manifest        = manifest;
    pal_state.manifest_handle = manifest_handle;
    pal_state.exec            = exec;
    pal_state.exec_handle     = exec_handle;

    const char * first_argv = *argv;
    argc--;
    argv++;

    if (is_parent && exec_handle) {
        first_argv = exec;
        if (pal_state.root_config) {
            char cfgbuf[CONFIG_MAX];
            ret = get_config(pal_state.root_config, "loader.execname", cfgbuf,
                             CONFIG_MAX);
            if (ret > 0)
                first_argv = remalloc(cfgbuf, ret + 1);
        }
    }

    if (pal_state.root_config)
        load_libraries();

    if (exec_handle) {
#if PROFILING == 1
        unsigned long before_load_exec = _DkSystemTimeQuery();
#endif

        ret = load_elf_object_by_handle(exec_handle, OBJECT_EXEC);
        if (ret < 0)
            init_fail(ret, PAL_STRERROR(ret));

#if PROFILING == 1
        pal_state.linking_time += _DkSystemTimeQuery() - before_load_exec;
#endif
    }

#if PROFILING == 1
    unsigned long before_tail = _DkSystemTimeQuery();
#endif

    if (pal_state.root_config) {
        read_envs(&envp);
        set_debug_type();
        set_syscall_symbol();
    }

    __pal_control.process_id         = _DkGetProcessId();
    __pal_control.host_id            = _DkGetHostId();
    __pal_control.manifest_handle    = manifest_handle;
    __pal_control.executable         = exec;
    __pal_control.parent_process     = parent_handle;
    __pal_control.first_thread       = thread_handle;

    _DkGetAvailableUserAddressRange(&__pal_control.user_address.start,
                                    &__pal_control.user_address.end);

    __pal_control.pagesize           = pal_state.pagesize;
    __pal_control.alloc_align        = pal_state.alloc_align;
    __pal_control.broadcast_stream   = _DkBroadcastStreamOpen();

    _DkGetCPUInfo(&__pal_control.cpu_info);
    __pal_control.mem_info.mem_total = _DkMemoryQuota();

#if PROFILING == 1
    pal_state.tail_startup_time      += _DkSystemTimeQuery() - before_tail;

    __pal_control.relocation_time     = pal_state.relocation_time;
    __pal_control.linking_time        = pal_state.linking_time;
    __pal_control.manifest_loading_time
                                      = pal_state.manifest_loading_time;
    __pal_control.allocation_time     = pal_state.slab_time;
    __pal_control.child_creation_time = is_parent ? 0 : pal_state.start_time -
                                        pal_state.process_create_time;
#endif

    /* Now we will start the execution */
    start_execution(first_argv, argc, argv, envp);

    /* We wish we will never reached here */
    init_fail(PAL_ERROR_DENIED, "unexpected termination");
}