| 231 | } |
| 232 | #endif |
| 233 | bool ElfLoader::loadProgram(KThread* thread, FsOpenNode* openNode, U32* eip) { |
| 234 | U8 buffer[sizeof(struct k_Elf32_Ehdr)] = { 0 }; |
| 235 | struct k_Elf32_Ehdr* hdr = (struct k_Elf32_Ehdr*)buffer; |
| 236 | U32 len = openNode->readNative(buffer, sizeof(buffer)); |
| 237 | U32 address=0xFFFFFFFF; |
| 238 | U32 reloc = 0; |
| 239 | |
| 240 | if (len!=sizeof(buffer)) { |
| 241 | return false; |
| 242 | } |
| 243 | if (!isValidElf(hdr)) |
| 244 | return false; |
| 245 | len=0; |
| 246 | openNode->seek(hdr->e_phoff); |
| 247 | for (U32 i=0;i<hdr->e_phnum;i++) { |
| 248 | struct k_Elf32_Phdr phdr; |
| 249 | openNode->readNative((U8*)&phdr, sizeof(struct k_Elf32_Phdr)); |
| 250 | if (phdr.p_type==PT_LOAD) { |
| 251 | if (phdr.p_paddr<address) { |
| 252 | address=phdr.p_paddr; |
| 253 | } |
| 254 | if (len<phdr.p_paddr+phdr.p_memsz) |
| 255 | len=phdr.p_paddr+phdr.p_memsz; |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | if (address>0x10000) { |
| 260 | reloc = 0; |
| 261 | len-=address; |
| 262 | } else { |
| 263 | reloc = ADDRESS_PROCESS_LOADER<<K_PAGE_SHIFT; |
| 264 | address = reloc; |
| 265 | } |
| 266 | |
| 267 | if (reloc) |
| 268 | address = thread->memory->mmap(thread, address, len, K_PROT_READ | K_PROT_WRITE | K_PROT_EXEC, K_MAP_PRIVATE | K_MAP_ANONYMOUS | K_MAP_FIXED, -1, 0); |
| 269 | thread->process->loaderBaseAddress = address; |
| 270 | thread->process->brkEnd = address+len; |
| 271 | thread->process->phdr = 0; |
| 272 | |
| 273 | for (U32 i=0;i<hdr->e_phnum;i++) { |
| 274 | struct k_Elf32_Phdr phdr; |
| 275 | openNode->seek(hdr->e_phoff+hdr->e_phentsize*i); |
| 276 | openNode->readNative((U8*)&phdr, sizeof(struct k_Elf32_Phdr)); |
| 277 | if (phdr.p_type==PT_LOAD) { |
| 278 | if (!reloc) { |
| 279 | U32 addr = phdr.p_paddr; |
| 280 | U32 sectionLen = phdr.p_memsz; |
| 281 | |
| 282 | if (phdr.p_paddr & 0xFFF) { |
| 283 | addr &= 0xFFFFF000; |
| 284 | sectionLen+=(phdr.p_memsz+(phdr.p_paddr-addr)); |
| 285 | } |
| 286 | thread->memory->mmap(thread, addr, sectionLen, K_PROT_READ | K_PROT_WRITE | K_PROT_EXEC, K_MAP_PRIVATE | K_MAP_ANONYMOUS | K_MAP_FIXED, -1, 0); |
| 287 | } |
| 288 | if (phdr.p_filesz>0) { |
| 289 | if (phdr.p_offset<=hdr->e_phoff && hdr->e_phoff<phdr.p_offset+phdr.p_filesz) { |
| 290 | thread->process->phdr = reloc+phdr.p_paddr+hdr->e_phoff-phdr.p_offset; |
nothing calls this directly
no test coverage detected