[PATCH 4/8] [Include]: created a wine only unwind.h include file for CPU specific unwind information

Eric Pouech eric.pouech at orange.fr
Sat Mar 20 03:47:39 CDT 2010


(and maps the definition to what MSDN states as field names)

A+
---

 dlls/ntdll/signal_x86_64.c |  144 ++++++++++++++++++--------------------------
 include/wine/unwind.h      |   82 +++++++++++++++++++++++++
 2 files changed, 140 insertions(+), 86 deletions(-)
 create mode 100644 include/wine/unwind.h


diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 6c64443..df0727a 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -50,6 +50,7 @@
 #include "ntdll_misc.h"
 #include "wine/debug.h"
 #include "wine/dwarf.h"
+#include "wine/unwind.h"
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
 #include <valgrind/memcheck.h>
@@ -212,35 +213,6 @@ union handler_data
     ULONG handler;
 };
 
-struct opcode
-{
-    BYTE offset;
-    BYTE code : 4;
-    BYTE info : 4;
-};
-
-struct UNWIND_INFO
-{
-    BYTE version : 3;
-    BYTE flags : 5;
-    BYTE prolog;
-    BYTE count;
-    BYTE frame_reg : 4;
-    BYTE frame_offset : 4;
-    struct opcode opcodes[1];  /* info->count entries */
-    /* followed by handler_data */
-};
-
-#define UWOP_PUSH_NONVOL     0
-#define UWOP_ALLOC_LARGE     1
-#define UWOP_ALLOC_SMALL     2
-#define UWOP_SET_FPREG       3
-#define UWOP_SAVE_NONVOL     4
-#define UWOP_SAVE_NONVOL_FAR 5
-#define UWOP_SAVE_XMM128     8
-#define UWOP_SAVE_XMM128_FAR 9
-#define UWOP_PUSH_MACHFRAME  10
-
 static void dump_unwind_info( ULONG64 base, RUNTIME_FUNCTION *function )
 {
     static const char * const reg_names[16] =
@@ -248,7 +220,7 @@ static void dump_unwind_info( ULONG64 base, RUNTIME_FUNCTION *function )
           "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15" };
 
     union handler_data *handler_data;
-    struct UNWIND_INFO *info;
+    UNWIND_INFO *info;
     unsigned int i, count;
 
     TRACE( "**** func %x-%x\n", function->BeginAddress, function->EndAddress );
@@ -263,76 +235,76 @@ static void dump_unwind_info( ULONG64 base, RUNTIME_FUNCTION *function )
             function = next;
             continue;
         }
-        info = (struct UNWIND_INFO *)((char *)base + function->UnwindData);
+        info = (UNWIND_INFO *)((char *)base + function->UnwindData);
 
         TRACE( "unwind info at %p flags %x prolog 0x%x bytes function %p-%p\n",
-               info, info->flags, info->prolog,
+               info, info->Flags, info->SizeOfProlog,
                (char *)base + function->BeginAddress, (char *)base + function->EndAddress );
 
-        if (info->frame_reg)
+        if (info->FrameRegister)
             TRACE( "    frame register %s offset 0x%x(%%rsp)\n",
-                   reg_names[info->frame_reg], info->frame_offset * 16 );
+                   reg_names[info->FrameRegister], info->FrameOffset * 16 );
 
-        for (i = 0; i < info->count; i++)
+        for (i = 0; i < info->CountOfCodes; i++)
         {
-            TRACE( "    0x%x: ", info->opcodes[i].offset );
-            switch (info->opcodes[i].code)
+            TRACE( "    0x%x: ", info->UnwindCode[i].CodeOffset );
+            switch (info->UnwindCode[i].UnwindOp)
             {
             case UWOP_PUSH_NONVOL:
-                TRACE( "pushq %%%s\n", reg_names[info->opcodes[i].info] );
+                TRACE( "pushq %%%s\n", reg_names[info->UnwindCode[i].OpInfo] );
                 break;
             case UWOP_ALLOC_LARGE:
-                if (info->opcodes[i].info)
+                if (info->UnwindCode[i].OpInfo)
                 {
-                    count = *(DWORD *)&info->opcodes[i+1];
+                    count = *(DWORD *)&info->UnwindCode[i+1];
                     i += 2;
                 }
                 else
                 {
-                    count = *(USHORT *)&info->opcodes[i+1] * 8;
+                    count = *(USHORT *)&info->UnwindCode[i+1] * 8;
                     i++;
                 }
                 TRACE( "subq $0x%x,%%rsp\n", count );
                 break;
             case UWOP_ALLOC_SMALL:
-                count = (info->opcodes[i].info + 1) * 8;
+                count = (info->UnwindCode[i].OpInfo + 1) * 8;
                 TRACE( "subq $0x%x,%%rsp\n", count );
                 break;
             case UWOP_SET_FPREG:
                 TRACE( "leaq 0x%x(%%rsp),%s\n",
-                     info->frame_offset * 16, reg_names[info->frame_reg] );
+                     info->FrameOffset * 16, reg_names[info->FrameRegister] );
                 break;
             case UWOP_SAVE_NONVOL:
-                count = *(USHORT *)&info->opcodes[i+1] * 8;
-                TRACE( "movq %%%s,0x%x(%%rsp)\n", reg_names[info->opcodes[i].info], count );
+                count = *(USHORT *)&info->UnwindCode[i+1] * 8;
+                TRACE( "movq %%%s,0x%x(%%rsp)\n", reg_names[info->UnwindCode[i].OpInfo], count );
                 i++;
                 break;
             case UWOP_SAVE_NONVOL_FAR:
-                count = *(DWORD *)&info->opcodes[i+1];
-                TRACE( "movq %%%s,0x%x(%%rsp)\n", reg_names[info->opcodes[i].info], count );
+                count = *(DWORD *)&info->UnwindCode[i+1];
+                TRACE( "movq %%%s,0x%x(%%rsp)\n", reg_names[info->UnwindCode[i].OpInfo], count );
                 i += 2;
                 break;
             case UWOP_SAVE_XMM128:
-                count = *(USHORT *)&info->opcodes[i+1] * 16;
-                TRACE( "movaps %%xmm%u,0x%x(%%rsp)\n", info->opcodes[i].info, count );
+                count = *(USHORT *)&info->UnwindCode[i+1] * 16;
+                TRACE( "movaps %%xmm%u,0x%x(%%rsp)\n", info->UnwindCode[i].OpInfo, count );
                 i++;
                 break;
             case UWOP_SAVE_XMM128_FAR:
-                count = *(DWORD *)&info->opcodes[i+1];
-                TRACE( "movaps %%xmm%u,0x%x(%%rsp)\n", info->opcodes[i].info, count );
+                count = *(DWORD *)&info->UnwindCode[i+1];
+                TRACE( "movaps %%xmm%u,0x%x(%%rsp)\n", info->UnwindCode[i].OpInfo, count );
                 i += 2;
                 break;
             case UWOP_PUSH_MACHFRAME:
-                TRACE( "PUSH_MACHFRAME %u\n", info->opcodes[i].info );
+                TRACE( "PUSH_MACHFRAME %u\n", info->UnwindCode[i].OpInfo );
                 break;
             default:
-                FIXME( "unknown code %u\n", info->opcodes[i].code );
+                FIXME( "unknown code %u\n", info->UnwindCode[i].UnwindOp );
                 break;
             }
         }
 
-        handler_data = (union handler_data *)&info->opcodes[(info->count + 1) & ~1];
-        if (info->flags & UNW_FLAG_CHAININFO)
+        handler_data = (union handler_data *)&info->UnwindCode[(info->CountOfCodes + 1) & ~1];
+        if (info->Flags & UNW_FLAG_CHAININFO)
         {
             TRACE( "    chained to function %p-%p\n",
                    (char *)base + handler_data->chain.BeginAddress,
@@ -340,7 +312,7 @@ static void dump_unwind_info( ULONG64 base, RUNTIME_FUNCTION *function )
             function = &handler_data->chain;
             continue;
         }
-        if (info->flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
+        if (info->Flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
             TRACE( "    handler %p data at %p\n",
                    (char *)base + handler_data->handler, &handler_data->handler + 1 );
         break;
@@ -2178,12 +2150,12 @@ static void set_float_reg( CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *ctx_
     if (ctx_ptr) ctx_ptr->u1.FloatingContext[reg] = &context->u.s.Xmm0 + reg;
 }
 
-static int get_opcode_size( struct opcode op )
+static int get_opcode_size( UNWIND_CODE op )
 {
-    switch (op.code)
+    switch (op.UnwindOp)
     {
     case UWOP_ALLOC_LARGE:
-        return 2 + (op.info != 0);
+        return 2 + (op.OpInfo != 0);
     case UWOP_SAVE_NONVOL:
     case UWOP_SAVE_XMM128:
         return 2;
@@ -2330,7 +2302,7 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
 {
     union handler_data *handler_data;
     ULONG64 frame, off;
-    struct UNWIND_INFO *info;
+    UNWIND_INFO *info;
     unsigned int i, prolog_offset;
 
     TRACE( "type %x rip %lx rsp %lx\n", type, pc, context->Rsp );
@@ -2339,20 +2311,20 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
     frame = *frame_ret = context->Rsp;
     for (;;)
     {
-        info = (struct UNWIND_INFO *)((char *)base + function->UnwindData);
-        handler_data = (union handler_data *)&info->opcodes[(info->count + 1) & ~1];
+        info = (UNWIND_INFO *)((char *)base + function->UnwindData);
+        handler_data = (union handler_data *)&info->UnwindCode[(info->CountOfCodes + 1) & ~1];
 
-        if (info->version != 1)
+        if (info->Version != 1)
         {
-            FIXME( "unknown unwind info version %u at %p\n", info->version, info );
+            FIXME( "unknown unwind info version %u at %p\n", info->Version, info );
             return NULL;
         }
 
-        if (info->frame_reg)
-            frame = get_int_reg( context, info->frame_reg ) - info->frame_offset * 16;
+        if (info->FrameRegister)
+            frame = get_int_reg( context, info->FrameRegister ) - info->FrameOffset * 16;
 
         /* check if in prolog */
-        if (pc >= base + function->BeginAddress && pc < base + function->BeginAddress + info->prolog)
+        if (pc >= base + function->BeginAddress && pc < base + function->BeginAddress + info->SizeOfProlog)
         {
             prolog_offset = pc - base - function->BeginAddress;
         }
@@ -2367,52 +2339,52 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
             }
         }
 
-        for (i = 0; i < info->count; i += get_opcode_size(info->opcodes[i]))
+        for (i = 0; i < info->CountOfCodes; i += get_opcode_size(info->UnwindCode[i]))
         {
-            if (prolog_offset < info->opcodes[i].offset) continue; /* skip it */
+            if (prolog_offset < info->UnwindCode[i].CodeOffset) continue; /* skip it */
 
-            switch (info->opcodes[i].code)
+            switch (info->UnwindCode[i].UnwindOp)
             {
             case UWOP_PUSH_NONVOL:  /* pushq %reg */
-                set_int_reg( context, ctx_ptr, info->opcodes[i].info, *(ULONG64 *)context->Rsp );
+                set_int_reg( context, ctx_ptr, info->UnwindCode[i].OpInfo, *(ULONG64 *)context->Rsp );
                 context->Rsp += sizeof(ULONG64);
                 break;
             case UWOP_ALLOC_LARGE:  /* subq $nn,%rsp */
-                if (info->opcodes[i].info) context->Rsp += *(DWORD *)&info->opcodes[i+1];
-                else context->Rsp += *(USHORT *)&info->opcodes[i+1] * 8;
+                if (info->UnwindCode[i].OpInfo) context->Rsp += *(DWORD *)&info->UnwindCode[i+1];
+                else context->Rsp += *(USHORT *)&info->UnwindCode[i+1] * 8;
                 break;
             case UWOP_ALLOC_SMALL:  /* subq $n,%rsp */
-                context->Rsp += (info->opcodes[i].info + 1) * 8;
+                context->Rsp += (info->UnwindCode[i].OpInfo + 1) * 8;
                 break;
             case UWOP_SET_FPREG:  /* leaq nn(%rsp),%framereg */
                 context->Rsp = *frame_ret = frame;
                 break;
             case UWOP_SAVE_NONVOL:  /* movq %reg,n(%rsp) */
-                off = frame + *(USHORT *)&info->opcodes[i+1] * 8;
-                set_int_reg( context, ctx_ptr, info->opcodes[i].info, *(ULONG64 *)off );
+                off = frame + *(USHORT *)&info->UnwindCode[i+1] * 8;
+                set_int_reg( context, ctx_ptr, info->UnwindCode[i].OpInfo, *(ULONG64 *)off );
                 break;
             case UWOP_SAVE_NONVOL_FAR:  /* movq %reg,nn(%rsp) */
-                off = frame + *(DWORD *)&info->opcodes[i+1];
-                set_int_reg( context, ctx_ptr, info->opcodes[i].info, *(ULONG64 *)off );
+                off = frame + *(DWORD *)&info->UnwindCode[i+1];
+                set_int_reg( context, ctx_ptr, info->UnwindCode[i].OpInfo, *(ULONG64 *)off );
                 break;
             case UWOP_SAVE_XMM128:  /* movaps %xmmreg,n(%rsp) */
-                off = frame + *(USHORT *)&info->opcodes[i+1] * 16;
-                set_float_reg( context, ctx_ptr, info->opcodes[i].info, *(M128A *)off );
+                off = frame + *(USHORT *)&info->UnwindCode[i+1] * 16;
+                set_float_reg( context, ctx_ptr, info->UnwindCode[i].OpInfo, *(M128A *)off );
                 break;
             case UWOP_SAVE_XMM128_FAR:  /* movaps %xmmreg,nn(%rsp) */
-                off = frame + *(DWORD *)&info->opcodes[i+1];
-                set_float_reg( context, ctx_ptr, info->opcodes[i].info, *(M128A *)off );
+                off = frame + *(DWORD *)&info->UnwindCode[i+1];
+                set_float_reg( context, ctx_ptr, info->UnwindCode[i].OpInfo, *(M128A *)off );
                 break;
             case UWOP_PUSH_MACHFRAME:
-                FIXME( "PUSH_MACHFRAME %u\n", info->opcodes[i].info );
+                FIXME( "PUSH_MACHFRAME %u\n", info->UnwindCode[i].OpInfo );
                 break;
             default:
-                FIXME( "unknown code %u\n", info->opcodes[i].code );
+                FIXME( "unknown code %u\n", info->UnwindCode[i].UnwindOp );
                 break;
             }
         }
 
-        if (!(info->flags & UNW_FLAG_CHAININFO)) break;
+        if (!(info->Flags & UNW_FLAG_CHAININFO)) break;
         function = &handler_data->chain;  /* restart with the chained info */
     }
 
@@ -2420,7 +2392,7 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
     context->Rip = *(ULONG64 *)context->Rsp;
     context->Rsp += sizeof(ULONG64);
 
-    if (!(info->flags & type)) return NULL;  /* no matching handler */
+    if (!(info->Flags & type)) return NULL;  /* no matching handler */
     if (prolog_offset != ~0) return NULL;  /* inside prolog */
 
     *data = &handler_data->handler + 1;
diff --git a/include/wine/unwind.h b/include/wine/unwind.h
new file mode 100644
index 0000000..910b8e8
--- /dev/null
+++ b/include/wine/unwind.h
@@ -0,0 +1,82 @@
+/* CPU specific stack unwind definitions
+ *
+ * Copyright 2009 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef __x86_64__
+
+/* as described on MSDN */
+
+typedef enum _UNWIND_OP_CODES
+{
+    UWOP_PUSH_NONVOL = 0,
+    UWOP_ALLOC_LARGE,
+    UWOP_ALLOC_SMALL,
+    UWOP_SET_FPREG,
+    UWOP_SAVE_NONVOL,
+    UWOP_SAVE_NONVOL_FAR,
+    UWOP_SAVE_XMM128,
+    UWOP_SAVE_XMM128_FAR,
+    UWOP_PUSH_MACHFRAME
+} UNWIND_CODE_OPS;
+
+typedef union _UNWIND_CODE
+{
+    struct
+    {
+        BYTE CodeOffset;
+        BYTE UnwindOp : 4;
+        BYTE OpInfo   : 4;
+    };
+    USHORT FrameOffset;
+} UNWIND_CODE, *PUNWIND_CODE;
+
+typedef struct _UNWIND_INFO
+{
+    BYTE Version       : 3;
+    BYTE Flags         : 5;
+    BYTE SizeOfProlog;
+    BYTE CountOfCodes;
+    BYTE FrameRegister : 4;
+    BYTE FrameOffset   : 4;
+    UNWIND_CODE UnwindCode[1]; /* actually CountOfCodes (aligned) */
+/*
+ *  union
+ *  {
+ *      OPTIONAL ULONG ExceptionHandler;
+ *      OPTIONAL ULONG FunctionEntry;
+ *  };
+ *  OPTIONAL ULONG ExceptionData[];
+ */
+} UNWIND_INFO, *PUNWIND_INFO;
+
+#define GetUnwindCodeEntry(info, index) \
+    ((info)->UnwindCode[index])
+
+#define GetLanguageSpecificDataPtr(info) \
+    ((PVOID)&GetUnwindCodeEntry((info),((info)->CountOfCodes + 1) & ~1))
+
+#define GetExceptionHandler(base, info) \
+    ((PEXCEPTION_HANDLER)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
+
+#define GetChainedFunctionEntry(base, info) \
+    ((PRUNTIME_FUNCTION)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
+
+#define GetExceptionDataPtr(info) \
+    ((PVOID)((PULONG)GetLanguageSpecificData(info) + 1)
+
+#endif






More information about the wine-patches mailing list