Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions FEXCore/Source/Interface/Core/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ bool Decoder::CheckRangeExecutable(uint64_t Address, uint64_t Size) {
ExecutableRangeWritable = RangeInfo.Writable;

if (RangeInfo.Size == 0) {
if (NonExecutableAddress == 0) {
NonExecutableAddress = Address;
}
return false;
}

Expand Down Expand Up @@ -1086,12 +1089,14 @@ Decoder::DecodedBlockStatus Decoder::DecodeInstruction(uint64_t PC) {
// Will be set if DecodeInstructionImpl tries to read non-executable memory
HitNonExecutableRange = false;
HitBadRelocation = false;
NonExecutableAddress = 0;
auto ErrorDuringDecoding = DecodeInstructionImpl(PC);

if (ErrorDuringDecoding != DecodedBlockStatus::SUCCESS || HitNonExecutableRange || HitBadRelocation) [[unlikely]] {
// Put an invalid instruction in the stream so the core can raise SIGILL if hit
// Error while decoding instruction. We don't know the table or instruction size
DecodeInst->TableInfo = nullptr;
DecodeInst->FaultAddress = NonExecutableAddress;
auto Result = ErrorDuringDecoding != DecodedBlockStatus::SUCCESS ? ErrorDuringDecoding :
DecodeInst->InstSize ? DecodedBlockStatus::PARTIAL_DECODE_INST :
HitNonExecutableRange ? DecodedBlockStatus::NOEXEC_INST :
Expand Down
1 change: 1 addition & 0 deletions FEXCore/Source/Interface/Core/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class Decoder final {
uint64_t ExecutableRangeEnd {};
bool ExecutableRangeWritable {};
bool HitNonExecutableRange {};
uint64_t NonExecutableAddress {};
bool HitBadRelocation {};

struct DecodeStream {
Expand Down
3 changes: 3 additions & 0 deletions FEXCore/Source/Interface/Core/JIT/MiscOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ DEF_OP(Break) {
LoadConstant(ARMEmitter::Size::i64Bit, TMP1, Constant);
str(TMP1, STATE, offsetof(FEXCore::Core::CpuStateFrame, SynchronousFaultData));

LoadConstant(ARMEmitter::Size::i64Bit, TMP1, Op->Reason.FaultAddress);
str(TMP1, STATE, offsetof(FEXCore::Core::CpuStateFrame, SynchronousFaultAddress));

switch (Op->Reason.Signal) {
case Core::FAULT_SIGILL:
ldr(TMP1, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.GuestSignal_SIGILL));
Expand Down
1 change: 1 addition & 0 deletions FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5158,6 +5158,7 @@ void OpDispatchBuilder::NoExecOp(OpcodeArgs) {
.Signal = Core::FAULT_SIGSEGV,
.TrapNumber = X86State::X86_TRAPNO_PF,
.si_code = 2, // SEGV_ACCERR
.FaultAddress = Op->FaultAddress,
});
}

Expand Down
1 change: 1 addition & 0 deletions FEXCore/Source/Interface/Core/X86Tables/X86Tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ struct DecodedOperand {

struct DecodedInst {
uint64_t PC;
uint64_t FaultAddress;

DecodedOperand Dest;
DecodedOperand Src[3];
Expand Down
1 change: 1 addition & 0 deletions FEXCore/Source/Interface/IR/IR.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
" uint8_t Signal;",
" uint8_t TrapNumber;",
" uint8_t si_code;",
" uint64_t FaultAddress;",
"};"
],
"IRTypes" : {
Expand Down
3 changes: 2 additions & 1 deletion FEXCore/Source/Interface/IR/IRDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ static void PrintArg(fextl::ostringstream* out, const IRListView*, FEXCore::IR::
*out << "{" << Arg.ErrorRegister << ".";
*out << static_cast<uint32_t>(Arg.Signal) << ".";
*out << static_cast<uint32_t>(Arg.TrapNumber) << ".";
*out << static_cast<uint32_t>(Arg.si_code) << "}";
*out << static_cast<uint32_t>(Arg.si_code) << ".";
*out << fmt::format("0x{:x}", Arg.FaultAddress) << "}";
}

static void PrintArg(fextl::ostringstream* out, const IRListView*, ShiftType Arg) {
Expand Down
2 changes: 2 additions & 0 deletions FEXCore/include/FEXCore/Core/CoreState.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ struct CpuStateFrame {
uint16_t err_code;
uint16_t _pad : 16;
} SynchronousFaultData;
uint64_t SynchronousFaultAddress {};

InternalThreadState* Thread;

Expand All @@ -444,4 +445,5 @@ static_assert(std::is_standard_layout<CpuStateFrame>::value, "This needs to be s
static_assert(sizeof(CpuStateFrame::SynchronousFaultData) == 8, "This needs to be 8 bytes");
static_assert(alignof(CpuStateFrame::SynchronousFaultDataStruct) == 8, "This needs to be 8 bytes");
static_assert(offsetof(CpuStateFrame, SynchronousFaultData) % 8 == 0, "This needs to be aligned");
static_assert(offsetof(CpuStateFrame, SynchronousFaultAddress) % 8 == 0, "This needs to be aligned");
} // namespace FEXCore::Core
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,11 @@ uint64_t SignalDelegator::SetupFrame_x64(FEXCore::Core::InternalThreadState* Thr

// Overwrite si_code and si_addr
guest_siginfo->si_code = Thread->CurrentFrame->SynchronousFaultData.si_code;
guest_siginfo->si_addr = reinterpret_cast<void*>(ContextBackup->OriginalRIP);
const bool IsGeneratedPageFault = Frame->SynchronousFaultData.Signal == FEXCore::Core::FAULT_SIGSEGV &&
Frame->SynchronousFaultData.TrapNo == FEXCore::X86State::X86_TRAPNO_PF;
const uint64_t FaultAddress =
IsGeneratedPageFault && Frame->SynchronousFaultAddress ? Frame->SynchronousFaultAddress : ContextBackup->OriginalRIP;
guest_siginfo->si_addr = reinterpret_cast<void*>(FaultAddress);
Signal = Frame->SynchronousFaultData.Signal;
} else {
guest_uctx->uc_mcontext.gregs[FEXCore::x86_64::FEX_REG_TRAPNO] = ConvertSignalToTrapNo(Signal, HostSigInfo);
Expand Down Expand Up @@ -790,7 +794,12 @@ uint64_t SignalDelegator::SetupRTFrame_ia32(FEXCore::Core::InternalThreadState*
case SigInfoLayout::LAYOUT_FAULT:
// Macro expansion to get the si_addr
// This is the address trying to be accessed, not the RIP
guest_uctx->info._sifields._sigfault.addr = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(HostSigInfo->si_addr));
if (ContextBackup->FaultToTopAndGeneratedException && Frame->SynchronousFaultData.Signal == FEXCore::Core::FAULT_SIGSEGV &&
Frame->SynchronousFaultData.TrapNo == FEXCore::X86State::X86_TRAPNO_PF && Frame->SynchronousFaultAddress) {
guest_uctx->info._sifields._sigfault.addr = static_cast<uint32_t>(Frame->SynchronousFaultAddress);
} else {
guest_uctx->info._sifields._sigfault.addr = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(HostSigInfo->si_addr));
}
break;
case SigInfoLayout::LAYOUT_FAULT_RIP:
// Macro expansion to get the si_addr
Expand Down
3 changes: 2 additions & 1 deletion Source/Windows/ARM64EC/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,8 @@ static void RethrowGuestException(const EXCEPTION_RECORD& Rec, ARM64_NT_CONTEXT&
EFlags &= ~(1 << FEXCore::X86State::RFLAG_TF_RAW_LOC);
CTX->SetFlagsFromCompactedEFLAGS(Thread, EFlags);

Args->Rec = FEX::Windows::HandleGuestException(Fault, Rec, Args->Context.Pc, Args->Context.X8, Args->Context.X0);
Args->Rec = FEX::Windows::HandleGuestException(Fault, Thread->CurrentFrame->SynchronousFaultAddress, Rec, Args->Context.Pc,
Args->Context.X8, Args->Context.X0);
if (Args->Rec.ExceptionCode == EXCEPTION_SINGLE_STEP) {
Args->Context.Cpsr &= ~(1 << 21); // PSTATE.SS
} else if (Args->Rec.ExceptionCode == EXCEPTION_BREAKPOINT) {
Expand Down
4 changes: 2 additions & 2 deletions Source/Windows/Common/Exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace FEX::Windows {
template<typename TReg>
static inline EXCEPTION_RECORD HandleGuestException(FEXCore::Core::CpuStateFrame::SynchronousFaultDataStruct& Fault,
static inline EXCEPTION_RECORD HandleGuestException(FEXCore::Core::CpuStateFrame::SynchronousFaultDataStruct& Fault, uint64_t FaultAddress,
const EXCEPTION_RECORD& Src, TReg& Rip, TReg Rax, TReg Cx) {
EXCEPTION_RECORD Dst = Src;
Dst.ExceptionAddress = reinterpret_cast<void*>(Rip);
Expand Down Expand Up @@ -68,7 +68,7 @@ static inline EXCEPTION_RECORD HandleGuestException(FEXCore::Core::CpuStateFrame
// A page-fault raised by an explicit break in JIT code is always an execute fault
Dst.NumberParameters = 2;
Dst.ExceptionInformation[0] = EXCEPTION_EXECUTE_FAULT;
Dst.ExceptionInformation[1] = Rip;
Dst.ExceptionInformation[1] = FaultAddress ? FaultAddress : Rip;
return Dst;
default: LogMan::Msg::EFmt("Unknown SIGSEGV trap: {}", Fault.TrapNo); break;
}
Expand Down
3 changes: 2 additions & 1 deletion Source/Windows/WOW64/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,8 @@ bool BTCpuResetToConsistentStateImpl(EXCEPTION_POINTERS* Ptrs) {
LogMan::Msg::DFmt("pc: {:X} eip: {:X}", Context->Pc, WowContext.Eip);

auto& Fault = Thread->CurrentFrame->SynchronousFaultData;
*Exception = FEX::Windows::HandleGuestException(Fault, *Exception, WowContext.Eip, WowContext.Eax, WowContext.Ecx);
*Exception = FEX::Windows::HandleGuestException(Fault, Thread->CurrentFrame->SynchronousFaultAddress, *Exception, WowContext.Eip,
WowContext.Eax, WowContext.Ecx);
if (Exception->ExceptionCode == EXCEPTION_SINGLE_STEP) {
WowContext.EFlags &= ~(1 << FEXCore::X86State::RFLAG_TF_RAW_LOC);
}
Expand Down
3 changes: 0 additions & 3 deletions unittests/FEXLinuxTests/Known_Failures
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,3 @@ sigtest_sigmask.64
# Disabled since FEX's FaultSafeMemcpy is intentionally stub-implemented
syscalls_efault.32
syscalls_efault.64

# partial instruction decode is known to fail
noexec_protect.64
Loading