LinuxSyscalls: Always reconstruct RIP and EFLAGS when spilling from the JIT

This commit is contained in:
Billy Laws committed 2025-07-30 00:13:27 +01:00
1 parent 2556acb82d
commit 20331d52c3
3 files changed
+10 -22

No files matched your search

@@ -108,12 +108,8 @@ GdbServer::GdbServer(FEXCore::Context::Context* ctx, FEX::HLE::SignalDelegator*
ThreadObject->GdbInfo = {};
ThreadObject->GdbInfo->Signal = Signal;
ThreadObject->GdbInfo->SignalPC = ArchHelpers::Context::GetPc(ucontext);
this->SignalDelegation->SpillSRA(Thread, ucontext, Thread->CurrentFrame->InSyscallInfo);
memcpy(ThreadObject->GdbInfo->GPRs, ArchHelpers::Context::GetArmGPRs(ucontext), sizeof(ThreadObject->GdbInfo->GPRs));
ThreadObject->GdbInfo->PState = ArchHelpers::Context::GetArmPState(ucontext);
// Let GDB know that we have a signal
this->Break(Thread, Signal);
@@ -304,16 +300,8 @@ GdbServer::GDBContextDefinition GdbServer::GenerateContextDefinition(const FEX::
// Encode the GDB context definition
memcpy(&GDB.gregs[0], &state.gregs[0], sizeof(GDB.gregs));
if (ThreadObject->GdbInfo.has_value()) {
GDB.rip = CTX->RestoreRIPFromHostPC(ThreadObject->Thread, ThreadObject->GdbInfo->SignalPC);
const bool WasInJIT = CTX->IsAddressInCodeBuffer(ThreadObject->Thread, ThreadObject->GdbInfo->SignalPC);
GDB.eflags = CTX->ReconstructCompactedEFLAGS(ThreadObject->Thread, WasInJIT, const_cast<uint64_t*>(ThreadObject->GdbInfo->GPRs),
ThreadObject->GdbInfo->PState);
} else {
GDB.rip = ThreadObject->Thread->CurrentFrame->State.rip;
GDB.eflags = CTX->ReconstructCompactedEFLAGS(ThreadObject->Thread, false, nullptr, 0);
}
GDB.rip = ThreadObject->Thread->CurrentFrame->State.rip;
GDB.eflags = CTX->ReconstructCompactedEFLAGS(ThreadObject->Thread, false, nullptr, 0);
for (size_t i = 0; i < FEXCore::Core::CPUState::NUM_MMS; ++i) {
memcpy(&GDB.mm[i], &state.mm[i], sizeof(GDB.mm[i]));
@@ -110,6 +110,8 @@ void SignalDelegator::RegisterHostSignalHandler(int Signal, HostSignalDelegatorF
void SignalDelegator::SpillSRA(FEXCore::Core::InternalThreadState* Thread, void* ucontext, uint32_t IgnoreMask) {
#ifdef _M_ARM_64
Thread->CurrentFrame->State.rip = CTX->RestoreRIPFromHostPC(Thread, ArchHelpers::Context::GetPc(ucontext));
for (size_t i = 0; i < Config.SRAGPRCount; i++) {
const uint8_t SRAIdxMap = Config.SRAGPRMapping[i];
if (IgnoreMask & (1U << SRAIdxMap)) {
@@ -132,6 +134,10 @@ void SignalDelegator::SpillSRA(FEXCore::Core::InternalThreadState* Thread, void*
memcpy(&Thread->CurrentFrame->State.xmm.sse.data[i][0], &FPR, sizeof(__uint128_t));
}
}
uint32_t EFlags =
CTX->ReconstructCompactedEFLAGS(Thread, true, ArchHelpers::Context::GetArmGPRs(ucontext), ArchHelpers::Context::GetArmPState(ucontext));
CTX->SetFlagsFromCompactedEFLAGS(Thread, EFlags);
#endif
}
@@ -354,11 +360,8 @@ bool SignalDelegator::HandleDispatcherGuestSignal(FEXCore::Core::InternalThreadS
// siginfo_t
siginfo_t* HostSigInfo = reinterpret_cast<siginfo_t*>(info);
// Backup where we think the RIP currently is
ContextBackup->OriginalRIP = CTX->RestoreRIPFromHostPC(Thread, ArchHelpers::Context::GetPc(ucontext));
// Calculate eflags upfront.
uint32_t eflags = CTX->ReconstructCompactedEFLAGS(Thread, WasInJIT, ArchHelpers::Context::GetArmGPRs(ucontext),
ArchHelpers::Context::GetArmPState(ucontext));
ContextBackup->OriginalRIP = Thread->CurrentFrame->State.rip;
uint32_t eflags = CTX->ReconstructCompactedEFLAGS(Thread, false, nullptr, 0);
if (Is64BitMode) {
NewGuestSP = SetupFrame_x64(Thread, ContextBackup, Frame, Signal, HostSigInfo, ucontext, GuestAction, GuestStack, NewGuestSP, eflags);
@@ -92,9 +92,6 @@ struct ThreadStateObject : public FEXCore::Allocator::FEXAllocOperators {
// GDB signal information
struct GdbInfoStruct {
int Signal {};
uint64_t SignalPC {};
uint64_t GPRs[32];
uint64_t PState {};
};
std::optional<GdbInfoStruct> GdbInfo;