mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 15:00:17 +02:00
At runtime, glxtest is mapped as follows: 0x000055fd9a030000 0x000055fd9a034000 0x4000 0x0 r--p glxtest 0x000055fd9a034000 0x000055fd9a038000 0x4000 0x3000 r-xp glxtest 0x000055fd9a038000 0x000055fd9a039000 0x1000 0x6000 rw-p glxtest 0x000055fd9a039000 0x000055fd9a03a000 0x1000 0x6000 rw-p glxtest The problem here is that the last two sections can't be distinguished solely by their mmap parameters. This would cause the wrong base address to be inferred for the last mapping. To fix this, we can be more permissive by allowing multiple candidates to be returned. In practice, this only affects non-code sections, so it's not a big issue either way.
51 lines
1.8 KiB
C++
51 lines
1.8 KiB
C++
// SPDX-License-Identifier: MIT
|
|
#pragma once
|
|
|
|
#include <FEXCore/Utils/TypeDefines.h>
|
|
#include <FEXCore/fextl/vector.h>
|
|
|
|
#include <cstdint>
|
|
#include <span>
|
|
|
|
#include <elf.h>
|
|
|
|
namespace FEXCore {
|
|
|
|
/**
|
|
* Infers the base virtual address from a file mapping (as described by parameters to a single
|
|
* call to mmap()).
|
|
*
|
|
* Usually the base address can uniquely be inferred, but in edge cases multiple possible
|
|
* candidates are returned.
|
|
*
|
|
* The file offset of any given mapping need not match its virtual address offset from the base
|
|
* mapping (file offset = 0). Instead, this function searches the corresponding ELF program headers
|
|
* for an entry that generated the given file mapping.
|
|
*/
|
|
inline fextl::vector<uint64_t>
|
|
InferMappingBaseAddress(std::span<const Elf64_Phdr> ProgramHeaders, uint64_t Addr, uint64_t Size, uint64_t FileOffset, int AccessFlags) {
|
|
fextl::vector<uint64_t> Ret;
|
|
for (auto& phdr : ProgramHeaders) {
|
|
if (phdr.p_type != PT_LOAD) {
|
|
// Skip headers that don't trigger memory mappings
|
|
continue;
|
|
}
|
|
|
|
if ((phdr.p_flags & (PF_X | PF_W | PF_R)) != (AccessFlags & (PF_X | PF_W | PF_R))) {
|
|
continue;
|
|
}
|
|
|
|
// The mapped file offset must be included at the start of the section header
|
|
auto SegmentStartOffset = phdr.p_offset - (phdr.p_vaddr & 0xfff);
|
|
if (FileOffset >= SegmentStartOffset && FileOffset < SegmentStartOffset + phdr.p_filesz &&
|
|
(FileOffset & Utils::FEX_PAGE_MASK) == (phdr.p_offset & Utils::FEX_PAGE_MASK)) {
|
|
// Compute VA offset relative to the base mapping
|
|
Ret.push_back(Addr - (phdr.p_vaddr - (phdr.p_offset & 0xfff)) + (ProgramHeaders[0].p_vaddr - (ProgramHeaders[0].p_offset & 0xfff)) -
|
|
(FileOffset - SegmentStartOffset));
|
|
}
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
} // namespace FEXCore
|