diff --git a/ARMeilleure/Signal/NativeSignalHandler.cs b/ARMeilleure/Signal/NativeSignalHandler.cs
index e8dc6ddaf4..77eabe2675 100644
--- a/ARMeilleure/Signal/NativeSignalHandler.cs
+++ b/ARMeilleure/Signal/NativeSignalHandler.cs
@@ -109,12 +109,6 @@ namespace ARMeilleure.Signal
 
                 if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
                 {
-                    // Unix siginfo struct locations.
-                    // NOTE: These are incredibly likely to be different between kernel version and architectures.
-
-                    config.StructAddressOffset = OperatingSystem.IsMacOS() ? 24 : 16; // si_addr
-                    config.StructWriteOffset = 8; // si_code
-
                     _signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
 
                     if (customSignalHandlerFactory != null)
@@ -251,18 +245,88 @@ namespace ARMeilleure.Signal
             return context.Copy(inRegionLocal);
         }
 
+        private static Operand GenerateUnixFaultAddress(EmitterContext context, Operand sigInfoPtr)
+        {
+            ulong structAddressOffset = OperatingSystem.IsMacOS() ? 24ul : 16ul; // si_addr
+            return context.Load(OperandType.I64, context.Add(sigInfoPtr, Const(structAddressOffset)));
+        }
+
+        private static Operand GenerateUnixWriteFlag(EmitterContext context, Operand ucontextPtr)
+        {
+            if (OperatingSystem.IsMacOS())
+            {
+                const ulong mcontextOffset = 48; // uc_mcontext
+                Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(mcontextOffset)));
+
+                if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+                {
+                    const ulong esrOffset = 8; // __es.__esr
+                    Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(esrOffset)));
+                    return context.BitwiseAnd(esr, Const(0x40ul));
+                }
+
+                if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
+                {
+                    const ulong errOffset = 4; // __es.__err
+                    Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(errOffset)));
+                    return context.BitwiseAnd(err, Const(2ul));
+                }
+            }
+            else if (OperatingSystem.IsLinux())
+            {
+                if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+                {
+                    Operand auxPtr = context.AllocateLocal(OperandType.I64);
+
+                    Operand loopLabel = Label();
+                    Operand successLabel = Label();
+
+                    const ulong auxOffset = 464; // uc_mcontext.__reserved
+                    const uint esrMagic = 0x45535201;
+
+                    context.Copy(auxPtr,  context.Add(ucontextPtr, Const(auxOffset)));
+
+                    context.MarkLabel(loopLabel);
+
+                    // _aarch64_ctx::magic
+                    Operand magic = context.Load(OperandType.I32, auxPtr);
+                    // _aarch64_ctx::size
+                    Operand size = context.Load(OperandType.I32, context.Add(auxPtr, Const(4ul)));
+
+                    context.BranchIf(successLabel, magic, Const(esrMagic), Comparison.Equal);
+
+                    context.Copy(auxPtr, context.Add(auxPtr, context.ZeroExtend32(OperandType.I64, size)));
+
+                    context.Branch(loopLabel);
+
+                    context.MarkLabel(successLabel);
+
+                    // esr_context::esr
+                    Operand esr = context.Load(OperandType.I64, context.Add(auxPtr, Const(8ul)));
+                    return context.BitwiseAnd(esr, Const(0x40ul));
+                }
+
+                if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
+                {
+                    const int errOffset = 192; // uc_mcontext.gregs[REG_ERR]
+                    Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(errOffset)));
+                    return context.BitwiseAnd(err, Const(2ul));
+                }
+            }
+
+            throw new PlatformNotSupportedException();
+        }
+
         private static UnixExceptionHandler GenerateUnixSignalHandler(IntPtr signalStructPtr)
         {
             EmitterContext context = new EmitterContext();
 
             // (int sig, SigInfo* sigInfo, void* ucontext)
             Operand sigInfoPtr = context.LoadArgument(OperandType.I64, 1);
+            Operand ucontextPtr = context.LoadArgument(OperandType.I64, 2);
 
-            Operand structAddressOffset = context.Load(OperandType.I64, Const((ulong)signalStructPtr + StructAddressOffset));
-            Operand structWriteOffset = context.Load(OperandType.I64, Const((ulong)signalStructPtr + StructWriteOffset));
-
-            Operand faultAddress = context.Load(OperandType.I64, context.Add(sigInfoPtr, context.ZeroExtend32(OperandType.I64, structAddressOffset)));
-            Operand writeFlag = context.Load(OperandType.I64, context.Add(sigInfoPtr, context.ZeroExtend32(OperandType.I64, structWriteOffset)));
+            Operand faultAddress = GenerateUnixFaultAddress(context, sigInfoPtr);
+            Operand writeFlag = GenerateUnixWriteFlag(context, ucontextPtr);
 
             Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.