Move partial unmap handler to the native signal handler (#3437)
* Initial commit with a lot of testing stuff. * Partial Unmap Cleanup Part 1 * Fix some minor issues, hopefully windows tests. * Disable partial unmap tests on macos for now Weird issue. * Goodbye magic number * Add COMPlus_EnableAlternateStackCheck for tests `COMPlus_EnableAlternateStackCheck` is needed for NullReferenceException handling to work on linux after registering the signal handler, due to how dotnet registers its own signal handler. * Address some feedback * Force retry when memory is mapped in memory tracking This case existed before, but returning `false` no longer retries, so it would crash immediately after unprotecting the memory... Now, we return `true` to deliberately retry. This case existed before (was just broken by this change) and I don't really want to look into fixing the issue right now. Technically, this means that on guest code partial unmaps will retry _due to this_ rather than hitting the handler. I don't expect this to cause any issues. This should fix random crashes in Xenoblade Chronicles 2. * Use IsRangeMapped * Suppress MockMemoryManager.UnmapEvent warning This event is not signalled by the mock memory manager. * Remove 4kb mapping
This commit is contained in:
parent
952d013c67
commit
14ce9e1567
24 changed files with 1355 additions and 391 deletions
|
@ -197,12 +197,29 @@ namespace ARMeilleure.Signal
|
|||
// Only call tracking if in range.
|
||||
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
|
||||
|
||||
context.Copy(inRegionLocal, Const(1));
|
||||
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~PageMask));
|
||||
|
||||
// Call the tracking action, with the pointer's relative offset to the base address.
|
||||
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
|
||||
context.Call(trackingActionPtr, OperandType.I32, offset, Const(PageSize), isWrite, Const(0));
|
||||
|
||||
context.Copy(inRegionLocal, Const(0));
|
||||
|
||||
Operand skipActionLabel = Label();
|
||||
|
||||
// Tracking action should be non-null to call it, otherwise assume false return.
|
||||
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
|
||||
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(PageSize), isWrite, Const(0));
|
||||
context.Copy(inRegionLocal, result);
|
||||
|
||||
context.MarkLabel(skipActionLabel);
|
||||
|
||||
// If the tracking action returns false or does not exist, it might be an invalid access due to a partial overlap on Windows.
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
context.BranchIfTrue(endLabel, inRegionLocal);
|
||||
|
||||
context.Copy(inRegionLocal, WindowsPartialUnmapHandler.EmitRetryFromAccessViolation(context));
|
||||
}
|
||||
|
||||
context.Branch(endLabel);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue