From f1c1c6ded690b34c8e5add75fecc96fff00848e5 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 2 Sep 2023 04:03:15 +0200 Subject: [PATCH] JitCache: Fix potentially dangling pointer to fast block map. Whenever JitBaseBlockCache::Clear() got called, it threw away the memory mapping for the fast block map and created a new one. This new mapping typically got mapped at the same address at the old one, but this is not guaranteed. The pointer to the mapping gets embedded in the generated dispatcher code in Jit64AsmRoutineManager::Generate(), which is only called once on game boot, so if the new mapping ended up at a different address than the old one, the pointer in the ASM pointed at garbage, leading to a crash. This fixes the issue by guaranteeing that the new mapping is mapped at the same address. --- .../Core/Core/PowerPC/JitCommon/JitCache.cpp | 31 +++++-------------- Source/Core/Core/PowerPC/JitCommon/JitCache.h | 2 +- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index a41ebb71b2..98ce48f24a 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -42,7 +42,11 @@ void JitBaseBlockCache::Init() { Common::JitRegister::Init(Config::Get(Config::MAIN_PERF_MAP_DIR)); - m_block_map_arena.GrabSHMSegment(FAST_BLOCK_MAP_SIZE, "dolphin-emu-jitblock"); + m_fast_block_map = reinterpret_cast(m_block_map_arena.Create(FAST_BLOCK_MAP_SIZE)); + if (m_fast_block_map) + m_fast_block_map_ptr = m_fast_block_map; + else + m_fast_block_map_ptr = m_fast_block_map_fallback.data(); Clear(); } @@ -51,12 +55,7 @@ void JitBaseBlockCache::Shutdown() { Common::JitRegister::Shutdown(); - if (m_fast_block_map) - { - m_block_map_arena.ReleaseView(m_fast_block_map, FAST_BLOCK_MAP_SIZE); - } - - m_block_map_arena.ReleaseSHMSegment(); + m_block_map_arena.Release(); } // This clears the JIT cache. It's called from JitCache.cpp when the JIT cache @@ -80,23 +79,7 @@ void JitBaseBlockCache::Clear() valid_block.ClearAll(); if (m_fast_block_map) - { - m_block_map_arena.ReleaseView(m_fast_block_map, FAST_BLOCK_MAP_SIZE); - m_block_map_arena.ReleaseSHMSegment(); - m_block_map_arena.GrabSHMSegment(FAST_BLOCK_MAP_SIZE, "dolphin-emu-jitblock"); - } - - m_fast_block_map = - reinterpret_cast(m_block_map_arena.CreateView(0, FAST_BLOCK_MAP_SIZE)); - - if (m_fast_block_map) - { - m_fast_block_map_ptr = m_fast_block_map; - } - else - { - m_fast_block_map_ptr = m_fast_block_map_fallback.data(); - } + m_block_map_arena.Clear(); } void JitBaseBlockCache::Reset() diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index d3f353e815..cf6f785d98 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -212,7 +212,7 @@ private: // This is used as a fast cache of block_map used in the assembly dispatcher. // It is implemented via a shm segment using m_block_map_arena. JitBlock** m_fast_block_map = 0; - Common::MemArena m_block_map_arena; + Common::LazyMemoryRegion m_block_map_arena; // An alternative for the above fast_block_map but without a shm segment // in case the shm memory region couldn't be allocated.