Jinoh Kang : ntdll: Properly parse UDF instruction in ARM.

Alexandre Julliard julliard at winehq.org
Tue May 31 15:57:59 CDT 2022


Module: wine
Branch: master
Commit: e2412025b20e63f8fcad3467c0ffcd7235f3d991
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e2412025b20e63f8fcad3467c0ffcd7235f3d991

Author: Jinoh Kang <jinoh.kang.kr at gmail.com>
Date:   Sun Dec  5 19:57:16 2021 +0900

ntdll: Properly parse UDF instruction in ARM.

Today, the UDF instruction handler code assumes Thumb mode code, and
cannot recognise the UDF.W form or equivalent instructions in ARM mode
encoding.

Fix this by generalising the UDF instruction parser code.

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>

---

 dlls/ntdll/unix/signal_arm.c | 35 ++++++++++++++++++++++++++++++++---
 1 file changed, 32 insertions(+), 3 deletions(-)

diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index ead14303436..c8edf22b170 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -360,6 +360,35 @@ static inline WORD get_error_code( const ucontext_t *sigcontext )
 }
 
 
+/***********************************************************************
+ *           get_udf_immediate
+ *
+ * Get the immediate operand if the PC is at a UDF instruction.
+ */
+static inline int get_udf_immediate( const ucontext_t *sigcontext )
+{
+    if (CPSR_sig(sigcontext) & 0x20)
+    {
+        WORD thumb_insn = *(WORD *)PC_sig(sigcontext);
+        if ((thumb_insn >> 8) == 0xde) return thumb_insn & 0xff;
+        if ((thumb_insn & 0xfff0) == 0xf7f0)  /* udf.w */
+        {
+            WORD ext = *(WORD *)(PC_sig(sigcontext) + 2);
+            if ((ext & 0xf000) == 0xa000) return ((thumb_insn & 0xf) << 12) | (ext & 0x0fff);
+        }
+    }
+    else
+    {
+        DWORD arm_insn = *(DWORD *)PC_sig(sigcontext);
+        if ((arm_insn & 0xfff000f0) == 0xe7f000f0)
+        {
+            return ((arm_insn >> 4) & 0xfff0) | (arm_insn & 0xf);
+        }
+    }
+    return -1;
+}
+
+
 /***********************************************************************
  *           save_context
  *
@@ -812,9 +841,9 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
     switch (get_trap_code(signal, context))
     {
     case TRAP_ARM_PRIVINFLT:   /* Invalid opcode exception */
-        switch (*(WORD *)PC_sig(context))
+        switch (get_udf_immediate( context ))
         {
-        case 0xdefb:  /* __fastfail */
+        case 0xfb:  /* __fastfail */
         {
             CONTEXT ctx;
             save_context( &ctx, sigcontext );
@@ -826,7 +855,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
             NtRaiseException( &rec, &ctx, FALSE );
             return;
         }
-        case 0xdefe:  /* breakpoint */
+        case 0xfe:  /* breakpoint */
             rec.ExceptionCode = EXCEPTION_BREAKPOINT;
             rec.NumberParameters = 1;
             break;




More information about the wine-cvs mailing list