INT32 elf_readphdrs(struct pm_task *task, INT32 (*ioread)(struct fsio_event_source *iosrc, UINT32 size, ADDR ptr), INT32 (*ioseek)(struct fsio_event_source *iosrc, UINT32 offset)) { UINT32 size; // seek to program headers possition size = task->loader_inf.elf_header.e_phentsize * task->loader_inf.elf_header.e_phnum; task->loader_inf.elf_pheaders = (BYTE*)kmalloc(size); if(task->loader_inf.elf_pheaders == NULL) { return -1; } if(task->loader_inf.elf_pheaders == NULL) { return -1; } task->io_finished.callback = elf_readh_finished_callback; if(ioread(&task->io_event_src, size, task->loader_inf.elf_pheaders)) { if(!elf_check(task)) return -1; task->loader_inf.stage = LOADER_STAGE_LOADED; return 1; } return 0; }
void* load_executable(char* filename) { // find file dir_entry* file = find_file(filename); // not found? if (!file) return 0; // calculate size and prepare buffer in kernel void* buffer = (void*) kmalloc(file->size + get_current_partition()->sectors_per_cluster * get_current_partition()->bytes_per_sector); // read to buffer read_file(file->cluster_high * 0x100 + file->cluster_low, buffer); // is it elf? if (elf_check(buffer)) return 0; // use program header to load Elf64_Phdr* ph = buffer + ((Elf64_Ehdr *) buffer)->e_phoff; uint64_t i; for (i = 0; i < ((Elf64_Ehdr *) buffer)->e_phnum; i++) { if (ph[i].p_type == 1) { if (!alloc_page((void*) ph[i].p_vaddr, ph[i].p_memsz / MEM_BLOCK_SIZE + 1)) return 0; memcpy((void*) ph[i].p_vaddr, buffer + ph[i].p_offset, ph[i].p_filesz); } } kfree(buffer); return (void*) ((uint64_t) ((Elf64_Ehdr *) buffer)->e_entry); }
INT32 elf_readh_finished_callback(struct fsio_event_source *iosrc, INT32 ioret) { struct pm_task *task = tsk_get(iosrc->id); struct pm_msg_response res_msg; res_msg.pm_type = (task->flags & TSK_SHARED_LIB)? PM_LOAD_LIBRARY : PM_CREATE_TASK; res_msg.status = PM_IO_ERROR; res_msg.new_id_aux = 0; if(ioret != IO_RET_OK) { if(task->flags & TSK_SHARED_LIB) { // we where loading a shared lib.. vmm_lib_loaded(task, FALSE); } else { if(task->creator_task != 0xFFFF) send_msg(task->creator_task, task->creator_task_port, &res_msg ); task->io_finished.callback = elf_fileclosed_callback; io_begin_close(iosrc); } } else { if(elf_check(task)) { if(task->flags & TSK_SHARED_LIB) { // we where loading a shared lib.. vmm_lib_loaded(task, TRUE); } else { /* Does this executable contain a PT_INTERP section? */ int phnum = task->loader_inf.elf_header.e_phnum; struct Elf32_Phdr *phdr; int i; for(i = 0; i < phnum; i++) { phdr = (struct Elf32_Phdr*)(task->loader_inf.elf_pheaders + task->loader_inf.elf_header.e_phentsize * i); if(phdr->p_type == PT_INTERP) break; } /* FIXME: We should get the name of the interpreter here.. */ if(!loader_task_loaded(task, (phdr->p_type == PT_INTERP)? "ld.so": NULL)) { if(task->flags & TSK_SHARED_LIB) { // we where loading a shared lib.. vmm_lib_loaded(task, FALSE); } else { task->io_finished.callback = elf_fileclosed_callback; io_begin_close(iosrc); } } } } else { if(task->flags & TSK_SHARED_LIB) { // we where loading a shared lib.. vmm_lib_loaded(task, FALSE); } else { if(task->flags & TSK_SHARED_LIB) { // we where loading a shared lib.. vmm_lib_loaded(task, FALSE); } else { res_msg.status = PM_INVALID_FILEFORMAT; if(task->creator_task != 0xFFFF) send_msg(task->creator_task, task->creator_task_port, &res_msg ); task->io_finished.callback = elf_fileclosed_callback; /* Close the file */ io_begin_close(iosrc); } } } } return 1; }
// elfファイルを解析して初期化する int elf_init(char* buff) { int i; struct Elf32_Phdr* ent,* ent_tmp; struct Elf32_Ehdr* elf_header; struct Elf32_Phdr* elf_program; printf("-------- elf_init --------\n"); elf_header = (struct Elf32_Ehdr*)buff; if(elf_check(elf_header)) return 1; m_magic[0] = elf_header->chare_ident[0]; m_magic[0] = elf_header->chare_ident[1]; m_magic[0] = elf_header->chare_ident[2]; m_magic[0] = elf_header->chare_ident[3]; m_fileclass = elf_header->chare_ident[4]; m_endian = elf_header->chare_ident[5]; m_elf_version = elf_header->chare_ident[6]; m_os_abi = elf_header->chare_ident[7]; m_abi_version = elf_header->chare_ident[8]; // e_ident[9...15] 未使用 m_e_type = littletobig((unsigned char*)&elf_header->e_type, 2); m_e_machine = littletobig((unsigned char*)&elf_header->e_machine, 2); m_e_version = littletobig((unsigned char*)&elf_header->e_version, 4); m_e_entry = littletobig((unsigned char*)&elf_header->e_entry, 4); m_e_phoff = littletobig((unsigned char*)&elf_header->e_phoff, 4); m_e_shoff = littletobig((unsigned char*)&elf_header->e_shoff, 4); m_e_flags = littletobig((unsigned char*)&elf_header->e_flags, 4); m_e_ehsize = littletobig((unsigned char*)&elf_header->e_ehsize, 2); m_e_phentsize = littletobig((unsigned char*)&elf_header->e_phentsize, 2); m_e_phnum = littletobig((unsigned char*)&elf_header->e_phnum, 2); m_e_shentsize = littletobig((unsigned char*)&elf_header->e_shentsize, 2); m_e_shnum = littletobig((unsigned char*)&elf_header->e_shnum, 2); m_e_shstrndx = littletobig((unsigned char*)&elf_header->e_shstrndx, 2); // プログラムヘッダの数は不定なのでリスト構造で保持する ent = (struct Elf32_Phdr*)malloc(sizeof(struct Elf32_Phdr)); m_program_hed = ent; // プログラムヘッダーの個数分繰り返す for(i = 0; i < m_e_phnum; i++) { // プログラムヘッダの開始番地取得 elf_program = (struct Elf32_Phdr*)&buff[ m_e_phoff + m_e_phentsize * i ]; // ヘッダの内容を保存 ent->p_type = littletobig((unsigned char*)&elf_program->p_type, 4); ent->p_offset = littletobig((unsigned char*)&elf_program->p_offset, 4); ent->p_vaddr = littletobig((unsigned char*)&elf_program->p_vaddr, 4); ent->p_paddr = littletobig((unsigned char*)&elf_program->p_paddr, 4); ent->p_filesz = littletobig((unsigned char*)&elf_program->p_filesz, 4); ent->p_memsz = littletobig((unsigned char*)&elf_program->p_memsz, 4); ent->p_flags = littletobig((unsigned char*)&elf_program->p_flags, 4); ent->p_align = littletobig((unsigned char*)&elf_program->p_align, 4); ent->next = 0x00; // リストの終端コード 0x00 // リスト構造で保存する ent_tmp = ent; ent = (struct Elf32_Phdr*)malloc(sizeof(struct Elf32_Phdr)); ent_tmp->next = ent; } return 0; }
/** Check a kernel image and determine the target type. * @param loader LAOS loader data structure. */ void laos_arch_check(laos_loader_t *loader) { if(!elf_check(loader->kernel, ELFCLASS32, ELFDATA2LSB, ELF_EM_ARM)) boot_error("Kernel image is not for this architecture"); loader->target = TARGET_TYPE_32BIT; }
int _exec(void *image, size_t size, int flags) { struct slt32_header *slt_hdr; struct slt32_entry *slt; struct elf32_ehdr *exec; struct elf_cache cache; void *entry; size_t i; const char *soname; char imgname[28]; /* check executable */ if (elf_check(image)) { return 1; } /*** POINT OF MAYBE RETURNING IF YOU, y'know, have to... ***/ /* copy executable high */ exec = (void*) sltalloc("dl.img:exec", size); if ((uintptr_t) image % PAGESZ) { /* not aligned, copy */ page_anon(exec, size, PROT_READ | PROT_WRITE); memcpy(exec, image, size); } else { /* aligned, use paging */ page_self(image, exec, size); } /*** POINT OF NO RETURN ***/ /* load dependencies */ for (i = 0;; i++) { soname = _dep(exec, i, 0); if (!soname) break; strlcpy(imgname, "dl.img:", 28); strlcat(imgname, soname, 28); slt = sltget_name(imgname); if (!slt) continue; _load((void*) slt->base, slt->size, RTLD_LAZY | RTLD_GLOBAL | RTLD_OVERWRITE); sltfree_name(imgname); } /* clear lower memory */ slt = (void*) SLT_BASE; slt_hdr = (void*) SLT_BASE; for (i = slt_hdr->first; i; i = slt[i].next) { if (slt[i].flags & SLT_FLAG_CLEANUP) { page_free((void*) slt[i].base, slt[i].size); } } /* load executable */ elf_load(exec, 0); exec = (void*) 0x100000; entry = (void*) exec->e_entry; elf_gencache(&cache, exec, 1); elfc_relocate_all(&cache); /* remove executable image */ sltfree_name("dl.img:exec"); /* reset event handler */ _when(0); /* enter executable */ dl_enter(entry); return 1; }