mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
Merge pull request #4783 from Sonicadvance1/save_restore_segments
LinuxSyscalls: Save and restore segment registers on signal
This commit is contained in:
2 files changed
+25
-1
No files matched your search
@@ -382,6 +382,15 @@ bool SignalDelegator::HandleDispatcherGuestSignal(FEXCore::Core::InternalThreadS
|
||||
Frame->State.flags[FEXCore::X86State::RFLAG_RF_LOC] = 0;
|
||||
Frame->State.flags[FEXCore::X86State::RFLAG_TF_RAW_LOC] = 0;
|
||||
|
||||
// Linux resets the CS and SS registers on signal handler.
|
||||
// This way signal handlers always go back to their original operating mode.
|
||||
// Doesn't matter for 32-bit processes as they can only be 32-bit, but does
|
||||
// matter for 64-bit processes as they could have potentially installed a 32-bit code segment.
|
||||
Frame->State.cs_idx = FEXCore::Core::CPUState::DEFAULT_USER_CS << 3;
|
||||
Frame->State.ss_idx = 0;
|
||||
Frame->State.cs_cached = Frame->State.CalculateGDTBase(*Frame->State.GetSegmentFromIndex(Frame->State, Frame->State.cs_idx));
|
||||
Frame->State.ss_cached = Frame->State.CalculateGDTBase(*Frame->State.GetSegmentFromIndex(Frame->State, Frame->State.ss_idx));
|
||||
|
||||
// The guest starts its signal frame with a zero initialized FPU
|
||||
// Set that up now. Little bit costly but it's a requirement
|
||||
// This state will be restored on rt_sigreturn
|
||||
|
||||
+16
-1
@@ -127,6 +127,15 @@ void SignalDelegator::RestoreFrame_x64(FEXCore::Core::InternalThreadState* Threa
|
||||
ArchHelpers::Context::SetState(ucontext, reinterpret_cast<uint64_t>(Frame));
|
||||
|
||||
Frame->State.rip = guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_RIP];
|
||||
|
||||
// Restore segments.
|
||||
// FS and GS are explicitly ignored here, as WRFSGSbase is used instead.
|
||||
Frame->State.cs_idx = (guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_CSGSFS] >> 0) & 0xffff;
|
||||
Frame->State.ss_idx = (guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_CSGSFS] >> 48) & 0xffff;
|
||||
|
||||
Frame->State.cs_cached = Frame->State.CalculateGDTBase(*Frame->State.GetSegmentFromIndex(Frame->State, Frame->State.cs_idx));
|
||||
Frame->State.ss_cached = Frame->State.CalculateGDTBase(*Frame->State.GetSegmentFromIndex(Frame->State, Frame->State.ss_idx));
|
||||
|
||||
// XXX: Full context setting
|
||||
CTX->SetFlagsFromCompactedEFLAGS(Thread, guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_EFL]);
|
||||
|
||||
@@ -377,7 +386,13 @@ uint64_t SignalDelegator::SetupFrame_x64(FEXCore::Core::InternalThreadState* Thr
|
||||
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_RIP] = ContextBackup->OriginalRIP;
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_EFL] = eflags;
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_CSGSFS] = 0;
|
||||
// This stores the CS/GS/FS selectors. It ALSO stores the SS selector in the top 16 bits...For some reason.
|
||||
// Despite the naming, the endianness is swapped from what you'd expect.
|
||||
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_CSGSFS] =
|
||||
((uint64_t)Frame->State.ss_idx << 48) |
|
||||
((uint64_t)Frame->State.fs_idx << 32) |
|
||||
((uint64_t)Frame->State.gs_idx << 16) |
|
||||
((uint64_t)Frame->State.cs_idx << 0);
|
||||
|
||||
// aarch64 and x86_64 siginfo_t matches. We can just copy this over
|
||||
// SI_USER could also potentially have random data in it, needs to be bit perfect
|
||||
|
||||
Reference in new issue
Block a user