Implement vm::page_executable (#6330)

Fixes segfaults when attenpting to set segfaults on non-executable memory.
This commit is contained in:
Eladash 2019-08-11 21:04:17 +03:00 committed by Ivan
parent 94d33003a3
commit 3ce18fd960
5 changed files with 15 additions and 17 deletions

View file

@ -1035,12 +1035,6 @@ void ppu_unload_prx(const lv2_prx& prx)
for (auto& seg : prx.segs) for (auto& seg : prx.segs)
{ {
if (seg.flags & 1)
{
// Segment was considered executable thus needing to free exec data
utils::memory_decommit(vm::g_exec_addr + size_t{seg.addr} * 2, size_t{seg.size} * 2);
}
vm::dealloc(seg.addr, vm::main); vm::dealloc(seg.addr, vm::main);
} }
} }

View file

@ -271,6 +271,7 @@ extern void ppu_register_range(u32 addr, u32 size)
// Register executable range at // Register executable range at
utils::memory_commit(&ppu_ref(addr), size * 2, utils::protection::rw); utils::memory_commit(&ppu_ref(addr), size * 2, utils::protection::rw);
vm::page_protect(addr, align(size, 0x10000), 0, vm::page_executable);
const u32 fallback = ::narrow<u32>(g_cfg.core.ppu_decoder == ppu_decoder_type::llvm ? const u32 fallback = ::narrow<u32>(g_cfg.core.ppu_decoder == ppu_decoder_type::llvm ?
reinterpret_cast<uptr>(ppu_recompiler_fallback) : reinterpret_cast<uptr>(ppu_fallback)); reinterpret_cast<uptr>(ppu_recompiler_fallback) : reinterpret_cast<uptr>(ppu_fallback));

View file

@ -101,11 +101,6 @@ error_code sys_overlay_unload_module(u32 ovlmid)
for (auto& seg : _main->segs) for (auto& seg : _main->segs)
{ {
if (seg.flags & 1)
{
utils::memory_decommit(vm::g_exec_addr + size_t{seg.addr} * 2, size_t{seg.size} * 2);
}
vm::dealloc(seg.addr); vm::dealloc(seg.addr);
} }

View file

@ -371,6 +371,7 @@ namespace vm
if (flags & page_executable) if (flags & page_executable)
{ {
// TODO
utils::memory_commit(g_exec_addr + addr * 2, size * 2); utils::memory_commit(g_exec_addr + addr * 2, size * 2);
} }
@ -424,10 +425,12 @@ namespace vm
if (i < end) if (i < end)
{ {
g_pages[i].flags |= flags_set; new_val = g_pages[i].flags;
g_pages[i].flags &= ~flags_clear; new_val |= flags_set;
new_val &= ~flags_clear;
new_val = g_pages[i].flags & (page_readable | page_writable); g_pages[i].flags.release(new_val);
new_val &= (page_readable | page_writable);
} }
if (new_val != start_value) if (new_val != start_value)
@ -464,9 +467,14 @@ namespace vm
break; break;
} }
if (g_pages[i].flags & page_executable) if (size == 0)
{ {
is_exec = true; is_exec = !!(g_pages[i].flags & page_executable);
}
else
{
// Must be consistent
verify(HERE), is_exec == !!(g_pages[i].flags & page_executable);
} }
size += 4096; size += 4096;

View file

@ -91,7 +91,7 @@ void breakpoint_list::HandleBreakpointRequest(u32 loc)
{ {
const auto cpu = this->cpu.lock(); const auto cpu = this->cpu.lock();
if (cpu->id_type() == 1 && vm::check_addr(loc)) if (cpu->id_type() == 1 && vm::check_addr(loc, 1, vm::page_allocated | vm::page_executable))
{ {
AddBreakpoint(loc); AddBreakpoint(loc);
} }