| 122 | } |
| 123 | |
| 124 | std::optional<uintptr_t> LoadElfFile(ELFParser& Elf, uintptr_t* BrkBase, FEX::HLE::SyscallHandler* const Handler, uint64_t LoadHint = 0) { |
| 125 | |
| 126 | uintptr_t LoadBase = 0; |
| 127 | uintptr_t BrkLoadBase = 0; |
| 128 | const bool DynELF = Elf.ehdr.e_type == ET_DYN; |
| 129 | const bool NeedsLateBRKMap = BrkBase && !DynELF; |
| 130 | |
| 131 | if (DynELF) { |
| 132 | // Allocate a base address plus BRK padding. |
| 133 | auto TotalSize = CalculateDYNELFSize(Elf.phdrs) + (BrkBase ? BRK_SIZE : 0); |
| 134 | LoadBase = |
| 135 | (uintptr_t)Handler->GuestMmap(nullptr, reinterpret_cast<void*>(LoadHint), TotalSize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
| 136 | if (FEX::HLE::HasSyscallError(LoadBase)) { |
| 137 | return {}; |
| 138 | } |
| 139 | |
| 140 | // fprintf(stderr, "elf %d: %lx-%lx\n", Elf.fd, LoadBase, LoadBase + TotalSize); |
| 141 | if (BrkBase) { |
| 142 | BrkLoadBase = LoadBase + (TotalSize - BRK_SIZE); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | for (const auto& Header : Elf.phdrs) { |
| 147 | if (Header.p_type != PT_LOAD) { |
| 148 | continue; |
| 149 | } |
| 150 | |
| 151 | int MapProt = MapFlags(Header); |
| 152 | int MapType = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED; |
| 153 | |
| 154 | if (!MapFile(Elf, LoadBase, Header, MapProt, MapType, Handler)) { |
| 155 | return {}; |
| 156 | } |
| 157 | |
| 158 | if (Header.p_memsz > Header.p_filesz) { |
| 159 | // clear bss |
| 160 | auto BSSStart = LoadBase + Header.p_vaddr + Header.p_filesz; |
| 161 | auto BSSPageStart = PAGE_ALIGN(BSSStart); |
| 162 | auto BSSPageEnd = PAGE_ALIGN(LoadBase + Header.p_vaddr + Header.p_memsz); |
| 163 | |
| 164 | // Only clear padding bytes if the section is writable |
| 165 | if (Header.p_flags & PF_W) { |
| 166 | memset((void*)BSSStart, 0, BSSPageStart - BSSStart); |
| 167 | } |
| 168 | |
| 169 | if (BSSPageStart != BSSPageEnd) { |
| 170 | auto bss = Handler->GuestMmap(nullptr, (void*)BSSPageStart, BSSPageEnd - BSSPageStart, MapProt, MapType | MAP_ANONYMOUS, -1, 0); |
| 171 | if (FEX::HLE::HasSyscallError(bss)) { |
| 172 | LogMan::Msg::EFmt("Failed to allocate BSS @ {}, {}\n", fmt::ptr(bss), errno); |
| 173 | return {}; |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | if (NeedsLateBRKMap) { |
| 179 | // Keep track of highest address for BRK in the case of non-dynamic ELF files. |
| 180 | auto memend = LoadBase + Header.p_vaddr + Header.p_memsz; |
| 181 |
nothing calls this directly
no test coverage detected