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); }
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"); }