mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
Merge pull request #4817 from neobrain/refactor_code_cache_new_interfaces
CodeCache: Introduce new interfaces
This commit is contained in:
27 files changed
+266
-302
No files matched your search
@@ -18,6 +18,7 @@ set (SRCS
|
||||
Common/JitSymbols.cpp
|
||||
Interface/Context/Context.cpp
|
||||
Interface/Core/LookupCache.cpp
|
||||
Interface/Core/CodeCache.cpp
|
||||
Interface/Core/Core.cpp
|
||||
Interface/Core/CPUBackend.cpp
|
||||
Interface/Core/Addressing.cpp
|
||||
@@ -57,7 +58,6 @@ set (SRCS
|
||||
Interface/Core/X86Tables/VEXTables.cpp
|
||||
Interface/Core/X86Tables/X87Tables.cpp
|
||||
Interface/GDBJIT/GDBJIT.cpp
|
||||
Interface/IR/AOTIR.cpp
|
||||
Interface/IR/IRDumper.cpp
|
||||
Interface/IR/IREmitter.cpp
|
||||
Interface/IR/PassManager.cpp
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "Interface/Core/CPUID.h"
|
||||
#include "Interface/Core/X86HelperGen.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/IR/AOTIR.h"
|
||||
#include <Interface/Core/JIT/DebugData.h>
|
||||
#include <Interface/IR/IntrusiveIRList.h>
|
||||
#include <FEXCore/Config/Config.h>
|
||||
#include <FEXCore/Core/Context.h>
|
||||
@@ -71,7 +71,23 @@ struct CustomIRResult {
|
||||
using BlockDelinkerFunc = void (*)(FEXCore::Core::CpuStateFrame* Frame, FEXCore::Context::ExitFunctionLinkData* Record);
|
||||
constexpr uint32_t TSC_SCALE_MAXIMUM = 1'000'000'000; ///< 1Ghz
|
||||
|
||||
class ContextImpl final : public FEXCore::Context::Context, CPU::CodeBufferManager {
|
||||
class CodeCache : public AbstractCodeCache {
|
||||
public:
|
||||
CodeCache(ContextImpl&);
|
||||
~CodeCache();
|
||||
|
||||
ContextImpl& CTX;
|
||||
bool IsGeneratingCache = false;
|
||||
|
||||
void LoadData(Core::InternalThreadState&, std::byte* MappedCacheFile, const ExecutableFileSectionInfo&) override;
|
||||
bool SaveData(Core::InternalThreadState&, int TargetFD, const ExecutableFileSectionInfo&, uint64_t SerializedBaseAddress) override;
|
||||
|
||||
void InitiateCacheGeneration() override {
|
||||
IsGeneratingCache = true;
|
||||
}
|
||||
};
|
||||
|
||||
class ContextImpl final : public FEXCore::Context::Context, public CPU::CodeBufferManager {
|
||||
public:
|
||||
// Context base class implementation.
|
||||
bool InitCore() override;
|
||||
@@ -141,10 +157,9 @@ public:
|
||||
FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) override;
|
||||
FEXCore::CPUID::FunctionResults RunCPUIDFunctionName(uint32_t Function, uint32_t Leaf, uint32_t CPU) override;
|
||||
|
||||
FEXCore::IR::AOTIRCacheEntry* LoadAOTIRCacheEntry(const fextl::string& Name) override;
|
||||
void UnloadAOTIRCacheEntry(FEXCore::IR::AOTIRCacheEntry* Entry) override;
|
||||
|
||||
void FinalizeAOTIRCache() override {}
|
||||
CodeCache& GetCodeCache() override {
|
||||
return CodeCache;
|
||||
}
|
||||
|
||||
void OnCodeBufferAllocated(CPU::CodeBuffer&) override;
|
||||
void ClearCodeCache(FEXCore::Core::InternalThreadState* Thread, bool NewCodeBuffer = true) override;
|
||||
@@ -224,6 +239,7 @@ public:
|
||||
FEXCore::HLE::SourcecodeResolver* SourcecodeResolver {};
|
||||
FEXCore::ThunkHandler* ThunkHandler {};
|
||||
fextl::unique_ptr<FEXCore::CPU::Dispatcher> Dispatcher;
|
||||
CodeCache CodeCache;
|
||||
|
||||
SignalDelegator* SignalDelegation {};
|
||||
X86GeneratedCode X86CodeGen;
|
||||
@@ -330,8 +346,6 @@ private:
|
||||
*/
|
||||
void InitializeCompiler(FEXCore::Core::InternalThreadState* Thread);
|
||||
|
||||
IR::AOTIRCaptureCache IRCaptureCache;
|
||||
|
||||
bool SupportsHardwareTSO = false;
|
||||
bool AtomicTSOEmulationEnabled = true;
|
||||
bool VectorAtomicTSOEmulationEnabled = false;
|
||||
|
||||
@@ -17,6 +17,10 @@ $end_info$
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
union Relocation;
|
||||
}
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
namespace IR {
|
||||
@@ -157,18 +161,7 @@ namespace CPU {
|
||||
virtual CompiledCode CompileCode(uint64_t Entry, uint64_t Size, bool SingleInst, const FEXCore::IR::IRListView* IR,
|
||||
FEXCore::Core::DebugData* DebugData, bool CheckTF) = 0;
|
||||
|
||||
/**
|
||||
* @brief Relocates a block of code from the JIT code object cache
|
||||
*
|
||||
* @param Entry - RIP of the entry
|
||||
* @param SerializationData - Serialization data referring to the object cache for `Entry`
|
||||
*
|
||||
* @return An executable function pointer relocated from the cache object
|
||||
*/
|
||||
[[nodiscard]]
|
||||
virtual void* RelocateJITObjectCode(uint64_t /* Entry */, const CodeSerialize::CodeObjectFileSection* /* SerializationData */) {
|
||||
return nullptr;
|
||||
}
|
||||
virtual fextl::vector<FEXCore::CPU::Relocation> TakeRelocations() = 0;
|
||||
|
||||
virtual void ClearCache() {}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include <Interface/Context/Context.h>
|
||||
|
||||
#include <FEXCore/HLE/SourcecodeResolver.h>
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
ExecutableFileInfo::~ExecutableFileInfo() = default;
|
||||
|
||||
} // namespace FEXCore
|
||||
|
||||
namespace FEXCore::Context {
|
||||
|
||||
CodeCache::CodeCache(ContextImpl& CTX_)
|
||||
: CTX(CTX_) {}
|
||||
CodeCache::~CodeCache() = default;
|
||||
|
||||
void CodeCache::LoadData(Core::InternalThreadState& Thread, std::byte* MappedCacheFile, const ExecutableFileSectionInfo& GuestRIPLookup) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
bool CodeCache::SaveData(Core::InternalThreadState& Thread, int fd, const ExecutableFileSectionInfo& SourceBinary, uint64_t SerializedBaseAddress) {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace FEXCore::Context
|
||||
@@ -18,6 +18,7 @@ $end_info$
|
||||
#include "Interface/Core/JIT/JITClass.h"
|
||||
#include "Interface/Core/Dispatcher/Dispatcher.h"
|
||||
#include "Interface/Core/X86Tables/X86Tables.h"
|
||||
#include <Interface/GDBJIT/GDBJIT.h>
|
||||
#include "Interface/IR/IR.h"
|
||||
#include "Interface/IR/IREmitter.h"
|
||||
#include "Interface/IR/Passes/RegisterAllocationPass.h"
|
||||
@@ -77,7 +78,7 @@ namespace FEXCore::Context {
|
||||
ContextImpl::ContextImpl(const FEXCore::HostFeatures& Features)
|
||||
: HostFeatures {Features}
|
||||
, CPUID {this}
|
||||
, IRCaptureCache {this} {
|
||||
, CodeCache {*this} {
|
||||
if (!Config.Is64BitMode()) {
|
||||
// When operating in 32-bit mode, the virtual memory we care about is only the lower 32-bits.
|
||||
Config.VirtualMemSize = 1ULL << 32;
|
||||
@@ -708,9 +709,9 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue
|
||||
|
||||
ContextImpl::CompileCodeResult ContextImpl::CompileCode(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestRIP, uint64_t MaxInst) {
|
||||
if (SourcecodeResolver && Config.GDBSymbols()) {
|
||||
auto AOTIRCacheEntry = SyscallHandler->LookupAOTIRCacheEntry(Thread, GuestRIP);
|
||||
if (AOTIRCacheEntry.Entry) {
|
||||
AOTIRCacheEntry.Entry->SourcecodeMap = SourcecodeResolver->GenerateMap(AOTIRCacheEntry.Entry->Filename, AOTIRCacheEntry.Entry->FileId);
|
||||
auto MappedSection = SyscallHandler->LookupExecutableFileSection(*Thread, GuestRIP);
|
||||
if (MappedSection) {
|
||||
MappedSection->FileInfo.SourcecodeMap = SourcecodeResolver->GenerateMap(MappedSection->FileInfo.Filename, MappedSection->FileInfo.FileId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,36 +786,44 @@ uintptr_t ContextImpl::CompileBlock(FEXCore::Core::CpuStateFrame* Frame, uint64_
|
||||
if (Config.BlockJITNaming()) {
|
||||
auto FragmentBasePtr = CompiledCode.BlockBegin;
|
||||
|
||||
if (DebugData) {
|
||||
auto GuestRIPLookup = SyscallHandler->LookupAOTIRCacheEntry(Thread, GuestRIP);
|
||||
auto GuestRIPLookup = SyscallHandler->LookupExecutableFileSection(*Thread, GuestRIP);
|
||||
|
||||
if (DebugData->Subblocks.size()) {
|
||||
for (auto& Subblock : DebugData->Subblocks) {
|
||||
auto BlockBasePtr = FragmentBasePtr + Subblock.HostCodeOffset;
|
||||
if (GuestRIPLookup.Entry) {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, CompiledCode.Size, GuestRIPLookup.Entry->Filename,
|
||||
GuestRIP - GuestRIPLookup.VAFileStart);
|
||||
} else {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, GuestRIP, Subblock.HostCodeSize);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (GuestRIPLookup.Entry) {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, CompiledCode.Size, GuestRIPLookup.Entry->Filename,
|
||||
GuestRIP - GuestRIPLookup.VAFileStart);
|
||||
if (DebugData->Subblocks.size()) {
|
||||
for (auto& Subblock : DebugData->Subblocks) {
|
||||
auto BlockBasePtr = FragmentBasePtr + Subblock.HostCodeOffset;
|
||||
if (GuestRIPLookup) {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, CompiledCode.Size, GuestRIPLookup->FileInfo.Filename,
|
||||
GuestRIP - GuestRIPLookup->FileStartVA);
|
||||
} else {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, GuestRIP, CompiledCode.Size);
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), BlockBasePtr, GuestRIP, Subblock.HostCodeSize);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (GuestRIPLookup) {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, CompiledCode.Size, GuestRIPLookup->FileInfo.Filename,
|
||||
GuestRIP - GuestRIPLookup->FileStartVA);
|
||||
} else {
|
||||
Symbols.Register(Thread->SymbolBuffer.get(), FragmentBasePtr, GuestRIP, CompiledCode.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Config.LibraryJITNaming() || Config.GDBSymbols()) {
|
||||
auto MappedSection = SyscallHandler->LookupExecutableFileSection(*Thread, GuestRIP);
|
||||
if (MappedSection) {
|
||||
if (Config.LibraryJITNaming()) {
|
||||
Symbols.RegisterNamedRegion(Thread->SymbolBuffer.get(), CodePtr, DebugData->HostCodeSize, MappedSection->FileInfo.Filename);
|
||||
}
|
||||
|
||||
if (Config.GDBSymbols()) {
|
||||
GDBJITRegister(MappedSection->FileInfo, MappedSection->FileStartVA, GuestRIP, (uintptr_t)CodePtr, *DebugData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear any relocations that might have been generated
|
||||
Thread->CPUBackend->ClearRelocations();
|
||||
|
||||
if (IRCaptureCache.PostCompileCode(Thread, CompiledCode.BlockBegin, GuestRIP, StartAddr, Length, DebugData.get())) {
|
||||
// Early exit
|
||||
return (uintptr_t)CodePtr;
|
||||
if (!CodeCache.IsGeneratingCache) {
|
||||
Thread->CPUBackend->ClearRelocations();
|
||||
}
|
||||
|
||||
if (NeedsAddGuestCodeRanges) {
|
||||
@@ -1009,13 +1018,6 @@ void ContextImpl::MonoBackpatcherWrite(FEXCore::Core::CpuStateFrame* Frame, uint
|
||||
CTX->SyscallHandler->InvalidateGuestCodeRange(Thread, Address, Size);
|
||||
}
|
||||
|
||||
IR::AOTIRCacheEntry* ContextImpl::LoadAOTIRCacheEntry(const fextl::string& filename) {
|
||||
auto rv = IRCaptureCache.LoadAOTIRCacheEntry(filename);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void ContextImpl::UnloadAOTIRCacheEntry(IR::AOTIRCacheEntry* Entry) {}
|
||||
|
||||
void ContextImpl::ConfigureAOTGen(FEXCore::Core::InternalThreadState* Thread, fextl::set<uint64_t>* ExternalBranches, uint64_t SectionMaxAddress) {
|
||||
Thread->FrontendDecoder->SetExternalBranches(ExternalBranches);
|
||||
Thread->FrontendDecoder->SetSectionMaxAddress(SectionMaxAddress);
|
||||
|
||||
@@ -81,35 +81,32 @@ void Arm64JITCore::InsertGuestRIPMove(ARMEmitter::Register Reg, uint64_t Constan
|
||||
Relocations.emplace_back(MoveABI);
|
||||
}
|
||||
|
||||
bool Arm64JITCore::ApplyRelocations(uint64_t GuestEntry, uint64_t CodeEntry, uint64_t CursorEntry, size_t NumRelocations,
|
||||
const char* EntryRelocations) {
|
||||
size_t DataIndex {};
|
||||
for (size_t j = 0; j < NumRelocations; ++j) {
|
||||
const FEXCore::CPU::Relocation* Reloc = reinterpret_cast<const FEXCore::CPU::Relocation*>(&EntryRelocations[DataIndex]);
|
||||
LOGMAN_THROW_A_FMT((DataIndex % alignof(Relocation)) == 0, "Alignment of relocation wasn't adhered to");
|
||||
bool Arm64JITCore::ApplyRelocations(uint64_t GuestEntry, std::span<std::byte> Code, std::span<const FEXCore::CPU::Relocation> Relocations) {
|
||||
const auto OrigBase = GetBufferBase();
|
||||
const auto OrigSize = GetBufferSize();
|
||||
const auto OrigOffset = GetCursorOffset();
|
||||
|
||||
switch (Reloc->Header.Type) {
|
||||
SetBuffer(reinterpret_cast<std::uint8_t*>(Code.data()), Code.size_bytes());
|
||||
for (auto& Reloc : Relocations) {
|
||||
switch (Reloc.Header.Type) {
|
||||
case FEXCore::CPU::RelocationTypes::RELOC_NAMED_SYMBOL_LITERAL: {
|
||||
uint64_t Pointer = GetNamedSymbolLiteral(Reloc->NamedSymbolLiteral.Symbol);
|
||||
uint64_t Pointer = GetNamedSymbolLiteral(Reloc.NamedSymbolLiteral.Symbol);
|
||||
// Relocation occurs at the cursorEntry + offset relative to that cursor
|
||||
SetCursorOffset(CursorEntry + Reloc->NamedSymbolLiteral.Offset);
|
||||
SetCursorOffset(Reloc.NamedSymbolLiteral.Offset);
|
||||
|
||||
// Generate a literal so we can place it
|
||||
dc64(Pointer);
|
||||
|
||||
DataIndex += sizeof(Reloc->NamedSymbolLiteral);
|
||||
break;
|
||||
}
|
||||
case FEXCore::CPU::RelocationTypes::RELOC_NAMED_THUNK_MOVE: {
|
||||
uint64_t Pointer = reinterpret_cast<uint64_t>(EmitterCTX->ThunkHandler->LookupThunk(Reloc->NamedThunkMove.Symbol));
|
||||
uint64_t Pointer = reinterpret_cast<uint64_t>(EmitterCTX->ThunkHandler->LookupThunk(Reloc.NamedThunkMove.Symbol));
|
||||
if (Pointer == ~0ULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Relocation occurs at the cursorEntry + offset relative to that cursor.
|
||||
SetCursorOffset(CursorEntry + Reloc->NamedThunkMove.Offset);
|
||||
LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc->NamedThunkMove.RegisterIndex), Pointer, true);
|
||||
DataIndex += sizeof(Reloc->NamedThunkMove);
|
||||
SetCursorOffset(Reloc.NamedThunkMove.Offset);
|
||||
LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc.NamedThunkMove.RegisterIndex), Pointer, true);
|
||||
break;
|
||||
}
|
||||
case FEXCore::CPU::RelocationTypes::RELOC_GUEST_RIP_MOVE: {
|
||||
@@ -117,18 +114,27 @@ bool Arm64JITCore::ApplyRelocations(uint64_t GuestEntry, uint64_t CodeEntry, uin
|
||||
// XXX: Should spin the relocation list, create a list of guest RIP moves, and ask for them all once, reduces lock contention.
|
||||
uint64_t Pointer = ~0ULL; // EmitterCTX->JITObjectCache->FindRelocatedRIP(Reloc->GuestRIPMove.GuestRIP);
|
||||
if (Pointer == ~0ULL) {
|
||||
SetBuffer(OrigBase, OrigSize);
|
||||
SetCursorOffset(OrigOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Relocation occurs at the cursorEntry + offset relative to that cursor.
|
||||
SetCursorOffset(CursorEntry + Reloc->GuestRIPMove.Offset);
|
||||
LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc->GuestRIPMove.RegisterIndex), Pointer, true);
|
||||
DataIndex += sizeof(Reloc->GuestRIPMove);
|
||||
SetCursorOffset(Reloc.GuestRIPMove.Offset);
|
||||
LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(Reloc.GuestRIPMove.RegisterIndex), Pointer, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetBuffer(OrigBase, OrigSize);
|
||||
SetCursorOffset(OrigOffset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fextl::vector<FEXCore::CPU::Relocation> Arm64JITCore::TakeRelocations() {
|
||||
return std::move(Relocations);
|
||||
}
|
||||
|
||||
} // namespace FEXCore::CPU
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/AllocatorHooks.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
union Relocation;
|
||||
} // namespace FEXCore::CPU
|
||||
|
||||
namespace FEXCore::Core {
|
||||
struct DebugDataSubblock {
|
||||
uint32_t HostCodeOffset;
|
||||
uint32_t HostCodeSize;
|
||||
};
|
||||
|
||||
struct DebugDataGuestOpcode {
|
||||
uint64_t GuestEntryOffset;
|
||||
ptrdiff_t HostEntryOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Contains debug data for a block of code for later debugger analysis
|
||||
*
|
||||
* Needs to remain around for as long as the code could be executed at least
|
||||
*/
|
||||
struct DebugData : public FEXCore::Allocator::FEXAllocOperators {
|
||||
uint64_t HostCodeSize; ///< The size of the code generated in the host JIT
|
||||
fextl::vector<DebugDataSubblock> Subblocks;
|
||||
fextl::vector<DebugDataGuestOpcode> GuestOpcodes;
|
||||
fextl::vector<FEXCore::CPU::Relocation>* Relocations;
|
||||
};
|
||||
} // namespace FEXCore::Core
|
||||
@@ -381,7 +381,9 @@ private:
|
||||
fextl::vector<FEXCore::CPU::Relocation> Relocations;
|
||||
|
||||
///< Relocation code loading
|
||||
bool ApplyRelocations(uint64_t GuestEntry, uint64_t CodeEntry, uint64_t CursorEntry, size_t NumRelocations, const char* EntryRelocations);
|
||||
bool ApplyRelocations(uint64_t GuestEntry, std::span<std::byte> Code, std::span<const FEXCore::CPU::Relocation>);
|
||||
|
||||
fextl::vector<FEXCore::CPU::Relocation> TakeRelocations() override;
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -42,19 +42,19 @@ void __attribute__((noinline)) __jit_debug_register_code() {
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry,
|
||||
FEXCore::Core::DebugData* DebugData) {
|
||||
auto map = Entry->SourcecodeMap.get();
|
||||
void GDBJITRegister(FEXCore::ExecutableFileInfo& Entry, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry,
|
||||
FEXCore::Core::DebugData& DebugData) {
|
||||
auto map = Entry.SourcecodeMap.get();
|
||||
|
||||
if (map) {
|
||||
auto FileOffset = GuestRIP - VAFileStart;
|
||||
|
||||
auto Sym = map->FindSymbolMapping(FileOffset);
|
||||
|
||||
auto SymName = HLE::SourcecodeSymbolMapping::SymName(Sym, Entry->Filename, HostEntry, FileOffset);
|
||||
auto SymName = HLE::SourcecodeSymbolMapping::SymName(Sym, Entry.Filename, HostEntry, FileOffset);
|
||||
|
||||
fextl::vector<gdb_line_mapping> Lines;
|
||||
for (const auto& GuestOpcode : DebugData->GuestOpcodes) {
|
||||
for (const auto& GuestOpcode : DebugData.GuestOpcodes) {
|
||||
auto Line = map->FindLineMapping(GuestRIP + GuestOpcode.GuestEntryOffset - VAFileStart);
|
||||
if (Line) {
|
||||
Lines.push_back({Line->LineNumber, HostEntry + GuestOpcode.HostEntryOffset});
|
||||
@@ -80,7 +80,7 @@ void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart,
|
||||
for (int i = 0; i < info->nblocks; i++) {
|
||||
strncpy(blocks[i].name, SymName.c_str(), 511);
|
||||
blocks[i].start = HostEntry;
|
||||
blocks[i].end = HostEntry + DebugData->HostCodeSize;
|
||||
blocks[i].end = HostEntry + DebugData.HostCodeSize;
|
||||
}
|
||||
|
||||
info->nlines = Lines.size();
|
||||
@@ -113,7 +113,7 @@ void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart,
|
||||
} // namespace FEXCore
|
||||
#else
|
||||
namespace FEXCore {
|
||||
void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry*, uintptr_t, uint64_t, uintptr_t, FEXCore::Core::DebugData*) {
|
||||
void GDBJITRegister(FEXCore::ExecutableFileInfo&, uintptr_t, uint64_t, uintptr_t, FEXCore::Core::DebugData&) {
|
||||
ERROR_AND_DIE_FMT("GDBSymbols support not compiled in");
|
||||
}
|
||||
} // namespace FEXCore
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
#include <Interface/IR/AOTIR.h>
|
||||
#include <FEXCore/Core/CodeCache.h>
|
||||
#include <Interface/Core/JIT/DebugData.h>
|
||||
|
||||
namespace FEXCore {
|
||||
void GDBJITRegister(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry,
|
||||
FEXCore::Core::DebugData* DebugData);
|
||||
}
|
||||
void GDBJITRegister(FEXCore::ExecutableFileInfo&, uintptr_t VAFileStart, uint64_t GuestRIP, uintptr_t HostEntry, FEXCore::Core::DebugData&);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "FEXHeaderUtils/Filesystem.h"
|
||||
#include "Interface/Context/Context.h"
|
||||
#include "Interface/IR/AOTIR.h"
|
||||
|
||||
#include <FEXCore/Utils/Allocator.h>
|
||||
#include <FEXCore/HLE/SyscallHandler.h>
|
||||
#include <FEXCore/fextl/fmt.h>
|
||||
|
||||
#include <Interface/Core/LookupCache.h>
|
||||
#include <Interface/GDBJIT/GDBJIT.h>
|
||||
|
||||
#include <xxhash.h>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
|
||||
bool AOTIRCaptureCache::PostCompileCode(FEXCore::Core::InternalThreadState* Thread, void* CodePtr, uint64_t GuestRIP, uint64_t StartAddr,
|
||||
uint64_t Length, FEXCore::Core::DebugData* DebugData) {
|
||||
|
||||
// Both generated ir and LibraryJITName need a named region lookup
|
||||
if (CTX->Config.LibraryJITNaming() || CTX->Config.GDBSymbols()) {
|
||||
|
||||
auto AOTIRCacheEntry = CTX->SyscallHandler->LookupAOTIRCacheEntry(Thread, GuestRIP);
|
||||
|
||||
if (AOTIRCacheEntry.Entry) {
|
||||
if (DebugData && CTX->Config.LibraryJITNaming()) {
|
||||
CTX->Symbols.RegisterNamedRegion(Thread->SymbolBuffer.get(), CodePtr, DebugData->HostCodeSize, AOTIRCacheEntry.Entry->Filename);
|
||||
}
|
||||
|
||||
if (CTX->Config.GDBSymbols()) {
|
||||
GDBJITRegister(AOTIRCacheEntry.Entry, AOTIRCacheEntry.VAFileStart, GuestRIP, (uintptr_t)CodePtr, DebugData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AOTIRCacheEntry* AOTIRCaptureCache::LoadAOTIRCacheEntry(const fextl::string& filename) {
|
||||
fextl::string base_filename = FHU::Filesystem::GetFilename(filename);
|
||||
|
||||
if (!base_filename.empty()) {
|
||||
auto filename_hash = XXH3_64bits(filename.c_str(), filename.size());
|
||||
|
||||
auto fileid = fextl::fmt::format("{}-{}-{}{}{}", base_filename, filename_hash,
|
||||
(CTX->Config.SMCChecks == FEXCore::Config::CONFIG_SMC_FULL) ? 'S' : 's',
|
||||
CTX->Config.TSOEnabled ? 'T' : 't', CTX->Config.ABILocalFlags ? 'L' : 'l');
|
||||
|
||||
std::unique_lock lk(AOTIRCacheLock);
|
||||
|
||||
auto Inserted = AOTIRCache.insert({fileid, AOTIRCacheEntry {.FileId = fileid, .Filename = filename}});
|
||||
auto Entry = &(Inserted.first->second);
|
||||
|
||||
return Entry;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace FEXCore::IR
|
||||
@@ -1,72 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/Utils/AllocatorHooks.h>
|
||||
#include <FEXCore/HLE/SourcecodeResolver.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/unordered_map.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
union Relocation;
|
||||
} // namespace FEXCore::CPU
|
||||
|
||||
namespace FEXCore::Core {
|
||||
struct InternalThreadState;
|
||||
struct DebugDataSubblock {
|
||||
uint32_t HostCodeOffset;
|
||||
uint32_t HostCodeSize;
|
||||
};
|
||||
|
||||
struct DebugDataGuestOpcode {
|
||||
uint64_t GuestEntryOffset;
|
||||
ptrdiff_t HostEntryOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Contains debug data for a block of code for later debugger analysis
|
||||
*
|
||||
* Needs to remain around for as long as the code could be executed at least
|
||||
*/
|
||||
struct DebugData : public FEXCore::Allocator::FEXAllocOperators {
|
||||
uint64_t HostCodeSize; ///< The size of the code generated in the host JIT
|
||||
fextl::vector<DebugDataSubblock> Subblocks;
|
||||
fextl::vector<DebugDataGuestOpcode> GuestOpcodes;
|
||||
fextl::vector<FEXCore::CPU::Relocation>* Relocations;
|
||||
};
|
||||
} // namespace FEXCore::Core
|
||||
|
||||
namespace FEXCore::Context {
|
||||
class ContextImpl;
|
||||
}
|
||||
|
||||
namespace FEXCore::IR {
|
||||
|
||||
struct AOTIRCacheEntry {
|
||||
fextl::unique_ptr<FEXCore::HLE::SourcecodeMap> SourcecodeMap;
|
||||
fextl::string FileId;
|
||||
fextl::string Filename;
|
||||
};
|
||||
|
||||
class AOTIRCaptureCache final {
|
||||
public:
|
||||
AOTIRCaptureCache(FEXCore::Context::ContextImpl* ctx)
|
||||
: CTX {ctx} {}
|
||||
|
||||
bool PostCompileCode(FEXCore::Core::InternalThreadState* Thread, void* CodePtr, uint64_t GuestRIP, uint64_t StartAddr, uint64_t Length,
|
||||
FEXCore::Core::DebugData* DebugData);
|
||||
|
||||
AOTIRCacheEntry* LoadAOTIRCacheEntry(const fextl::string& filename);
|
||||
|
||||
private:
|
||||
FEXCore::Context::ContextImpl* CTX;
|
||||
|
||||
std::shared_mutex AOTIRCacheLock;
|
||||
|
||||
fextl::unordered_map<fextl::string, FEXCore::IR::AOTIRCacheEntry> AOTIRCache;
|
||||
};
|
||||
|
||||
} // namespace FEXCore::IR
|
||||
+3
-8
@@ -78,14 +78,9 @@ When generating IR inside of the `OpDispatchBuilder` it is straight forward, jus
|
||||
This is an intrusive allocator that is used by the `OpDispatchBuilder` for storing IR data. It is a simple linear arena allocator without resizing capabilities.
|
||||
|
||||
### OpDispatchBuilder
|
||||
OpDispatchBuilder provides two routines for handling the IR outside of the class
|
||||
* `IRListView ViewIR();`
|
||||
* Returns a wrapper container class the allows you to view the IR. This doesn't take ownership of the IR data.
|
||||
* If the OpDispatcherBuilder changes its IR then changes are also visible to this class
|
||||
* `IRListView *CreateIRCopy()`
|
||||
* As the name says, it creates a new copy of the IR that is in the OpDispatchBuilder
|
||||
* Copying the IR only copies the memory used and doesn't have any free space for optimizations after this copy operation
|
||||
* Useful for tiered recompilers, AOT, and offline analysis
|
||||
OpDispatchBuilder provides `IRListView ViewIR()` for handling the IR outside of the class:
|
||||
* Returns a wrapper container class the allows you to view the IR. This doesn't take ownership of the IR data.
|
||||
* If the OpDispatcherBuilder changes its IR then changes are also visible to this class
|
||||
|
||||
This class uses two IntrusiveAllocator objects for tracking IR data. `ListData` and `Data` are the object names.
|
||||
* `ListData` is for tracking the doubly linked list of nodes
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace FEXCore {
|
||||
|
||||
namespace Core {
|
||||
struct InternalThreadState;
|
||||
} // namespace Core
|
||||
|
||||
namespace HLE {
|
||||
struct SourcecodeMap;
|
||||
} // namespace HLE
|
||||
|
||||
// Generic information associated with an executable file.
|
||||
struct ExecutableFileInfo {
|
||||
~ExecutableFileInfo();
|
||||
|
||||
fextl::unique_ptr<HLE::SourcecodeMap> SourcecodeMap;
|
||||
fextl::string FileId;
|
||||
fextl::string Filename;
|
||||
};
|
||||
|
||||
// Information associated with a specific section of an executable file
|
||||
struct ExecutableFileSectionInfo {
|
||||
ExecutableFileInfo& FileInfo;
|
||||
|
||||
// Start address that the file is mapped to.
|
||||
uintptr_t FileStartVA;
|
||||
};
|
||||
|
||||
class AbstractCodeCache {
|
||||
public:
|
||||
virtual ~AbstractCodeCache() = default;
|
||||
|
||||
/**
|
||||
* Loads a code cache from mapped memory and appends it to the current Core state.
|
||||
* TODO: Optionally recompiles all contained code blocks at runtime for validation.
|
||||
*/
|
||||
virtual void LoadData(Core::InternalThreadState&, std::byte* MappedCacheFile, const ExecutableFileSectionInfo&) = 0;
|
||||
|
||||
/**
|
||||
* Bundles the current Core state (CodeBuffer, GuestToHostMapping, ...) to a code cache and writes it to the given file descriptor.
|
||||
* Returns true on success.
|
||||
*/
|
||||
virtual bool SaveData(Core::InternalThreadState&, int TargetFD, const ExecutableFileSectionInfo&, uint64_t SerializedBaseAddress) = 0;
|
||||
|
||||
/**
|
||||
* Function to be called before compiling any code for caching purposes
|
||||
*/
|
||||
virtual void InitiateCacheGeneration() = 0;
|
||||
};
|
||||
|
||||
} // namespace FEXCore
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <FEXCore/Core/SignalDelegator.h>
|
||||
#include <FEXCore/Core/CodeCache.h>
|
||||
#include <FEXCore/Core/CPUID.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
#include <FEXCore/Utils/CompilerDefs.h>
|
||||
@@ -13,12 +14,7 @@
|
||||
#include <FEXCore/fextl/string.h>
|
||||
#include <FEXCore/fextl/vector.h>
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <span>
|
||||
|
||||
namespace FEXCore {
|
||||
class CodeLoader;
|
||||
struct HostFeatures;
|
||||
class ForkableSharedMutex;
|
||||
class ThunkHandler;
|
||||
@@ -29,17 +25,11 @@ struct CPUState;
|
||||
struct InternalThreadState;
|
||||
} // namespace FEXCore::Core
|
||||
|
||||
namespace FEXCore::CPU {
|
||||
class CPUBackend;
|
||||
}
|
||||
|
||||
namespace FEXCore::HLE {
|
||||
struct SyscallArguments;
|
||||
class SyscallHandler;
|
||||
} // namespace FEXCore::HLE
|
||||
|
||||
namespace FEXCore::IR {
|
||||
struct AOTIRCacheEntry;
|
||||
class IREmitter;
|
||||
} // namespace FEXCore::IR
|
||||
|
||||
@@ -148,10 +138,7 @@ public:
|
||||
FEX_DEFAULT_VISIBILITY virtual FEXCore::CPUID::XCRResults RunXCRFunction(uint32_t Function) = 0;
|
||||
FEX_DEFAULT_VISIBILITY virtual FEXCore::CPUID::FunctionResults RunCPUIDFunctionName(uint32_t Function, uint32_t Leaf, uint32_t CPU) = 0;
|
||||
|
||||
FEX_DEFAULT_VISIBILITY virtual FEXCore::IR::AOTIRCacheEntry* LoadAOTIRCacheEntry(const fextl::string& Name) = 0;
|
||||
FEX_DEFAULT_VISIBILITY virtual void UnloadAOTIRCacheEntry(FEXCore::IR::AOTIRCacheEntry* Entry) = 0;
|
||||
|
||||
FEX_DEFAULT_VISIBILITY virtual void FinalizeAOTIRCache() = 0;
|
||||
virtual AbstractCodeCache& GetCodeCache() = 0;
|
||||
|
||||
FEX_DEFAULT_VISIBILITY virtual void ClearCodeCache(FEXCore::Core::InternalThreadState* Thread, bool NewCodeBuffer = true) = 0;
|
||||
FEX_DEFAULT_VISIBILITY virtual void InvalidateGuestCodeRange(
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
struct AOTIRCacheEntry;
|
||||
}
|
||||
|
||||
namespace FEXCore::HLE {
|
||||
|
||||
struct SourcecodeLineMapping {
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <shared_mutex>
|
||||
#include <optional>
|
||||
|
||||
#include <FEXCore/Core/CodeCache.h>
|
||||
#include <FEXCore/IR/IR.h>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
struct AOTIRCacheEntry;
|
||||
}
|
||||
#include <FEXCore/fextl/string.h>
|
||||
|
||||
namespace FEXCore::Context {
|
||||
class Context;
|
||||
@@ -51,19 +49,6 @@ struct ExecutableRangeInfo {
|
||||
class SyscallHandler;
|
||||
class SourcecodeResolver;
|
||||
|
||||
struct AOTIRCacheEntryLookupResult {
|
||||
AOTIRCacheEntryLookupResult(FEXCore::IR::AOTIRCacheEntry* Entry, uintptr_t VAFileStart)
|
||||
: Entry(Entry)
|
||||
, VAFileStart(VAFileStart) {}
|
||||
|
||||
AOTIRCacheEntryLookupResult(AOTIRCacheEntryLookupResult&&) = default;
|
||||
|
||||
FEXCore::IR::AOTIRCacheEntry* Entry;
|
||||
uintptr_t VAFileStart;
|
||||
|
||||
friend class SyscallHandler;
|
||||
};
|
||||
|
||||
class SyscallHandler {
|
||||
public:
|
||||
virtual ~SyscallHandler() = default;
|
||||
@@ -82,7 +67,7 @@ public:
|
||||
virtual void MarkOvercommitRange(uint64_t Start, uint64_t Length) {}
|
||||
virtual void UnmarkOvercommitRange(uint64_t Start, uint64_t Length) {}
|
||||
virtual ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) = 0;
|
||||
virtual AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) = 0;
|
||||
virtual std::optional<ExecutableFileSectionInfo> LookupExecutableFileSection(Core::InternalThreadState& Thread, uint64_t GuestAddr) = 0;
|
||||
|
||||
virtual void PreCompile() {}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <algorithm>
|
||||
#include <fcntl.h>
|
||||
#include <memory_resource>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#ifndef _WIN32
|
||||
#include <linux/limits.h>
|
||||
#include <sys/sendfile.h>
|
||||
@@ -354,6 +354,11 @@ inline fextl::string GetFilename(const fextl::string& Path) {
|
||||
return PathToString(std::filesystem::path(Path).filename());
|
||||
}
|
||||
|
||||
inline std::string_view GetFilename(std::string_view Path) {
|
||||
auto Filename = PathToString(std::filesystem::path(Path).filename());
|
||||
return Path.substr(Path.size() - Filename.size());
|
||||
}
|
||||
|
||||
inline fextl::string ParentPath(const fextl::string& Path) {
|
||||
return PathToString(std::filesystem::path(Path).parent_path());
|
||||
}
|
||||
|
||||
@@ -460,8 +460,9 @@ public:
|
||||
}
|
||||
|
||||
// These are no-ops implementations of the SyscallHandler API
|
||||
FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override {
|
||||
return {0, 0};
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo>
|
||||
LookupExecutableFileSection(FEXCore::Core::InternalThreadState& Thread, uint64_t GuestAddr) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override {
|
||||
|
||||
@@ -22,8 +22,8 @@ public:
|
||||
}
|
||||
|
||||
// These are no-ops implementations of the SyscallHandler API
|
||||
FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override {
|
||||
return {0, 0};
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo> LookupExecutableFileSection(FEXCore::Core::InternalThreadState&, uint64_t) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override {
|
||||
|
||||
@@ -290,8 +290,8 @@ public:
|
||||
static bool HandleSegfault(FEXCore::Core::InternalThreadState* Thread, int Signal, void* info, void* ucontext);
|
||||
void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override;
|
||||
void InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override;
|
||||
// AOTIRCacheEntryLookupResult also includes a shared lock guard, so the pointed AOTIRCacheEntry return can be safely used
|
||||
FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) final override;
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo>
|
||||
LookupExecutableFileSection(FEXCore::Core::InternalThreadState& Thread, uint64_t GuestAddr) final override;
|
||||
|
||||
FEXCore::HLE::ExecutableRangeInfo QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) override;
|
||||
|
||||
|
||||
@@ -167,19 +167,19 @@ void SyscallHandler::InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState
|
||||
FEX::HLE::_SyscallHandler->InvalidateCodeRangeIfNecessary(Thread, Start, Length);
|
||||
}
|
||||
|
||||
// Used for AOT
|
||||
FEXCore::HLE::AOTIRCacheEntryLookupResult SyscallHandler::LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) {
|
||||
auto lk = FEXCore::GuardSignalDeferringSection<std::shared_lock>(VMATracking.Mutex, Thread);
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo>
|
||||
SyscallHandler::LookupExecutableFileSection(FEXCore::Core::InternalThreadState& Thread, uint64_t GuestAddr) {
|
||||
auto lk = FEXCore::GuardSignalDeferringSection<std::shared_lock>(VMATracking.Mutex, &Thread);
|
||||
|
||||
// Get the first mapping after GuestAddr, or end
|
||||
// GuestAddr is inclusive
|
||||
// If the write spans two pages, they will be flushed one at a time (generating two faults)
|
||||
auto Entry = VMATracking.FindVMAEntry(GuestAddr);
|
||||
if (Entry == VMATracking.VMAs.end()) {
|
||||
return {nullptr, 0};
|
||||
if (Entry == VMATracking.VMAs.end() || !Entry->second.Resource) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return {Entry->second.Resource ? Entry->second.Resource->AOTIRCacheEntry : nullptr, Entry->second.Base - Entry->second.Offset};
|
||||
return FEXCore::ExecutableFileSectionInfo {*Entry->second.Resource->MappedFile, Entry->second.Base - Entry->second.Offset};
|
||||
}
|
||||
|
||||
FEXCore::HLE::ExecutableRangeInfo SyscallHandler::QueryGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Address) {
|
||||
@@ -374,19 +374,19 @@ void SyscallHandler::TrackMmap(FEXCore::Core::InternalThreadState* Thread, uint6
|
||||
auto PathLength = FEX::get_fdpath(fd, Tmp);
|
||||
|
||||
if (PathLength != -1) {
|
||||
Tmp[PathLength] = '\0';
|
||||
auto [Iter, Inserted] = VMATracking.EmplaceMappedResource(mrid, VMATracking::MappedResource {nullptr, nullptr, 0});
|
||||
auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0});
|
||||
Resource = &Iter->second;
|
||||
|
||||
if (Inserted) {
|
||||
Resource->AOTIRCacheEntry = CTX->LoadAOTIRCacheEntry(fextl::string(Tmp, PathLength));
|
||||
Resource->MappedFile = fextl::make_unique<FEXCore::ExecutableFileInfo>();
|
||||
Resource->MappedFile->Filename = fextl::string(Tmp, PathLength);
|
||||
Resource->Iterator = Iter;
|
||||
}
|
||||
}
|
||||
} else if (flags & MAP_SHARED) {
|
||||
VMATracking::MRID mrid {VMATracking::SpecialDev::Anon, AnonSharedId++};
|
||||
|
||||
auto [Iter, Inserted] = VMATracking.EmplaceMappedResource(mrid, VMATracking::MappedResource {nullptr, nullptr, 0});
|
||||
auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, 0});
|
||||
LOGMAN_THROW_A_FMT(Inserted == true, "VMA tracking error");
|
||||
Resource = &Iter->second;
|
||||
Resource->Iterator = Iter;
|
||||
@@ -446,7 +446,7 @@ 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.EmplaceMappedResource(mrid, VMATracking::MappedResource {nullptr, nullptr, Length});
|
||||
auto [Iter, Inserted] = VMATracking.InsertMappedResource(mrid, {nullptr, nullptr, Length});
|
||||
auto Resource = &Iter->second;
|
||||
if (Inserted) {
|
||||
Resource->Iterator = Iter;
|
||||
|
||||
@@ -235,9 +235,6 @@ void VMATracking::DeleteVMARange(FEXCore::Context::Context* CTX, uintptr_t Base,
|
||||
// If linked to a Mapped Resource, remove from linked list and possibly delete the Mapped Resource
|
||||
if (Current->Resource) {
|
||||
if (ListRemove(Current) && Current->Resource != PreservedMappedResource) {
|
||||
if (Current->Resource->AOTIRCacheEntry) {
|
||||
CTX->UnloadAOTIRCacheEntry(Current->Resource->AOTIRCacheEntry);
|
||||
}
|
||||
MappedResources.erase(Current->Resource->Iterator);
|
||||
}
|
||||
}
|
||||
@@ -540,9 +537,6 @@ uintptr_t VMATracking::DeleteSHMRegion(FEXCore::Context::Context* CTX, uintptr_t
|
||||
do {
|
||||
if (Entry->second.Resource == Resource) {
|
||||
if (ListRemove(&Entry->second)) {
|
||||
if (Entry->second.Resource->AOTIRCacheEntry) {
|
||||
CTX->UnloadAOTIRCacheEntry(Entry->second.Resource->AOTIRCacheEntry);
|
||||
}
|
||||
MappedResources.erase(Entry->second.Resource->Iterator);
|
||||
}
|
||||
Entry = VMAs.erase(Entry);
|
||||
|
||||
@@ -5,12 +5,9 @@
|
||||
#include <tuple>
|
||||
|
||||
#include <FEXCore/fextl/map.h>
|
||||
#include <FEXCore/fextl/memory.h>
|
||||
#include <FEXCore/Utils/SignalScopeGuards.h>
|
||||
|
||||
namespace FEXCore::IR {
|
||||
struct AOTIRCacheEntry;
|
||||
}
|
||||
|
||||
namespace FEX::HLE::VMATracking {
|
||||
///// VMA (Virtual Memory Area) tracking /////
|
||||
|
||||
@@ -37,7 +34,7 @@ struct VMAEntry;
|
||||
struct MappedResource {
|
||||
using ContainerType = fextl::map<MRID, MappedResource>;
|
||||
|
||||
FEXCore::IR::AOTIRCacheEntry* AOTIRCacheEntry;
|
||||
fextl::unique_ptr<FEXCore::ExecutableFileInfo> MappedFile;
|
||||
// Pointer to lowest memory range this file is mapped to
|
||||
VMAEntry* FirstVMA;
|
||||
uint64_t Length; // 0 if not fixed size
|
||||
@@ -87,7 +84,7 @@ struct VMATracking {
|
||||
using VMACIterator = decltype(VMAs)::const_iterator;
|
||||
|
||||
// Find a VMA entry associated with the memory address.
|
||||
// Used by `mremap`, and SIGSEGV handler to find previously mapped ranges, and `AOTIR` cache to find cache entries.
|
||||
// Used by `mremap` and SIGSEGV handler to find previously mapped ranges, and CodeCache to find cache entries.
|
||||
// - Mutex must be at least shared_locked before calling
|
||||
VMACIterator FindVMAEntry(uint64_t GuestAddr) const;
|
||||
|
||||
@@ -114,11 +111,9 @@ struct VMATracking {
|
||||
// Returns the Size of the Shm or 0 if not found
|
||||
uintptr_t DeleteSHMRegion(FEXCore::Context::Context* Ctx, uintptr_t Base);
|
||||
|
||||
// Emplaces a new `MappedResource` to track.
|
||||
// Used for `mmap` and `shmat` resources; Anonymous, FD, and SHM depending on flags.
|
||||
template<class... Args>
|
||||
inline auto EmplaceMappedResource(Args&&... args) {
|
||||
return MappedResources.emplace(args...);
|
||||
// Adds a new `MappedResource` to track.
|
||||
inline auto InsertMappedResource(const MRID& mrid, MappedResource Resource) {
|
||||
return MappedResources.emplace(mrid, std::move(Resource));
|
||||
}
|
||||
private:
|
||||
bool ListRemove(VMAEntry* Mapping);
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace FEX::HLE {
|
||||
class SyscallHandler;
|
||||
}
|
||||
|
||||
#include <span>
|
||||
|
||||
namespace FEX::VDSO {
|
||||
struct VDSOMapping {
|
||||
void* VDSOBase {};
|
||||
|
||||
@@ -586,8 +586,8 @@ public:
|
||||
return {.NumArgs = 0, .HasReturn = false, .HostSyscallNumber = -1};
|
||||
}
|
||||
|
||||
FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override {
|
||||
return {0, 0};
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo> LookupExecutableFileSection(FEXCore::Core::InternalThreadState&, uint64_t) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override {
|
||||
|
||||
@@ -478,8 +478,8 @@ public:
|
||||
return {.NumArgs = 0, .HasReturn = false, .HostSyscallNumber = -1};
|
||||
}
|
||||
|
||||
FEXCore::HLE::AOTIRCacheEntryLookupResult LookupAOTIRCacheEntry(FEXCore::Core::InternalThreadState* Thread, uint64_t GuestAddr) override {
|
||||
return {0, 0};
|
||||
std::optional<FEXCore::ExecutableFileSectionInfo> LookupExecutableFileSection(FEXCore::Core::InternalThreadState&, uint64_t) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void MarkGuestExecutableRange(FEXCore::Core::InternalThreadState* Thread, uint64_t Start, uint64_t Length) override {
|
||||
|
||||
Reference in new issue
Block a user