| 34 | } |
| 35 | |
| 36 | bool MemoryManager::LoadSegments(const ElfW(Phdr)* phdr_table, size_t phdr_num, |
| 37 | void* mapped_file, size_t file_size) { |
| 38 | LOGD("Starting LoadSegments: phdr_num=%zu, file_size=%zu", phdr_num, file_size); |
| 39 | |
| 40 | for (size_t i = 0; i < phdr_num; ++i) { |
| 41 | const ElfW(Phdr)* phdr = &phdr_table[i]; |
| 42 | |
| 43 | if (phdr->p_type != PT_LOAD) { |
| 44 | continue; |
| 45 | } |
| 46 | |
| 47 | LOGD("Processing LOAD segment %zu: vaddr=0x%lx, memsz=0x%lx, filesz=0x%lx, offset=0x%lx", |
| 48 | i, phdr->p_vaddr, phdr->p_memsz, phdr->p_filesz, phdr->p_offset); |
| 49 | |
| 50 | ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_; |
| 51 | ElfW(Addr) seg_end = seg_start + phdr->p_memsz; |
| 52 | |
| 53 | ElfW(Addr) seg_page_start = PAGE_START(seg_start); |
| 54 | ElfW(Addr) seg_page_end = PAGE_END(seg_end); |
| 55 | |
| 56 | ElfW(Addr) seg_file_end = seg_start + phdr->p_filesz; |
| 57 | |
| 58 | ElfW(Addr) file_start = phdr->p_offset; |
| 59 | ElfW(Addr) file_end = file_start + phdr->p_filesz; |
| 60 | |
| 61 | ElfW(Addr) file_page_start = PAGE_START(file_start); |
| 62 | |
| 63 | if (file_end > file_size) { |
| 64 | LOGE("Invalid file size: file_end=0x%lx > file_size=0x%zx", file_end, file_size); |
| 65 | return false; |
| 66 | } |
| 67 | |
| 68 | if (phdr->p_filesz > 0) { |
| 69 | void* seg_addr = reinterpret_cast<void*>(seg_page_start); |
| 70 | size_t seg_size = seg_page_end - seg_page_start; |
| 71 | |
| 72 | if (mprotect(seg_addr, seg_size, PROT_READ | PROT_WRITE) < 0) { |
| 73 | LOGE("Cannot mprotect for loading: %s", strerror(errno)); |
| 74 | return false; |
| 75 | } |
| 76 | |
| 77 | void* src = static_cast<char*>(mapped_file) + phdr->p_offset; |
| 78 | void* dst = reinterpret_cast<void*>(seg_start); |
| 79 | |
| 80 | LOGD("Copying segment %zu: src=%p (offset=0x%lx), dst=%p, size=0x%lx", |
| 81 | i, src, phdr->p_offset, dst, phdr->p_filesz); |
| 82 | |
| 83 | if (static_cast<char*>(src) + phdr->p_filesz > static_cast<char*>(mapped_file) + file_size) { |
| 84 | LOGE("Source copy would exceed file bounds"); |
| 85 | return false; |
| 86 | } |
| 87 | |
| 88 | if (reinterpret_cast<ElfW(Addr)>(dst) + phdr->p_filesz > seg_page_end) { |
| 89 | LOGE("Destination copy would exceed segment bounds"); |
| 90 | return false; |
| 91 | } |
| 92 | |
| 93 | memcpy(dst, src, phdr->p_filesz); |