LinuxSyscalls: Use a multimap to store MappedResources

This allows for creating separate MappedResources when an ELF file is mapped
multiple times at different base addresses.
This commit is contained in:
Tony Wasserka committed 2025-10-20 18:00:25 +02:00
1 parent 02c00a87dd
commit 92428e5cbc
2 files changed
+34 -12

No files matched your search

@@ -388,11 +388,15 @@ std::optional<SyscallHandler::LateApplyExtendedVolatileMetadata> SyscallHandler:
char Tmp[PATH_MAX];
auto PathLength = FEX::get_fdpath(fd, Tmp);
auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0});
Resource = &Iter->second;
if (Inserted) {
Resource->Iterator = Iter;
auto [ResourceIt, ResourceEnd] = VMATracking.FindResources(mrid);
bool Inserted = false;
if (ResourceIt == ResourceEnd) {
// Create a new MappedResource for previously unseen file
ResourceIt = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0});
ResourceIt->second.Iterator = ResourceIt;
Inserted = true;
}
Resource = &ResourceIt->second;
// Only handle FDs that are backed by regular files that are executable
if (PathLength != -1 && S_ISREG(buf.st_mode) && (buf.st_mode & S_IXUSR)) {
@@ -419,8 +423,10 @@ std::optional<SyscallHandler::LateApplyExtendedVolatileMetadata> SyscallHandler:
} else if (flags & MAP_SHARED) {
VMATracking::MRID mrid {VMATracking::SpecialDev::Anon, AnonSharedId++};
auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0});
LOGMAN_THROW_A_FMT(Inserted == true, "VMA tracking error");
auto [Iter, IterEnd] = VMATracking.FindResources(mrid);
LOGMAN_THROW_A_FMT(Iter == IterEnd, "VMA tracking error");
Iter = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0});
Resource = &Iter->second;
Resource->Iterator = Iter;
} else {
@@ -480,11 +486,12 @@ void SyscallHandler::TrackMremap(FEXCore::Core::InternalThreadState* Thread, uin
void SyscallHandler::TrackShmat(FEXCore::Core::InternalThreadState* Thread, int shmid, uint64_t shmaddr, int shmflg, uint64_t Length) {
VMATracking::MRID mrid {VMATracking::SpecialDev::SHM, static_cast<uint64_t>(shmid)};
auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, Length});
auto Resource = &Iter->second;
if (Inserted) {
Resource->Iterator = Iter;
auto [Iter, IterEnd] = VMATracking.FindResources(mrid);
if (Iter == IterEnd) {
Iter = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, Length});
Iter->second.Iterator = Iter;
}
auto Resource = &Iter->second;
VMATracking.TrackVMARange(CTX, Resource, shmaddr, 0, Length, VMATracking::VMAFlags::fromFlags(MAP_SHARED), VMATracking::VMAProt::fromSHM(shmflg));
}
@@ -30,9 +30,16 @@ struct MRID {
struct VMAEntry;
// Used to all MAP_SHARED VMAs of a system resource.
/**
* Meta data associated to one system resource.
*
* Typically there is one instance of this type per ELF/PE file or special device.
* However if an ELF/PE file is mapped multiple times at different base addresses,
* there will be one separate MappedResource for each base address. The MRID
* is the same in this case.
*/
struct MappedResource {
using ContainerType = fextl::map<MRID, MappedResource>;
using ContainerType = fextl::multimap<MRID, MappedResource>;
fextl::unique_ptr<FEXCore::ExecutableFileInfo> MappedFile;
// Pointer to lowest memory range this file is mapped to
@@ -116,6 +123,14 @@ struct VMATracking {
return MappedResources.emplace(mrid, std::move(Resource));
}
// Returns an iterator pair spanning the range of all MappedResources matching the given MRID.
// Typically there is only one associated resource, however sometimes the same file gets mapped
// multiple times at different base addresses. In that case, each MappedResource will cover an
// exclusive set of VMAEntries that refer to a consistent base mapping address.
inline auto FindResources(const MRID& mrid) {
return MappedResources.equal_range(mrid);
}
private:
MappedResource::ContainerType MappedResources;
};