Eric Pouech : dbghelp: Extend dwarf stack unwinding by reading information out of . debug_frame sections.

Alexandre Julliard julliard at winehq.org
Fri Apr 2 10:17:10 CDT 2010


Module: wine
Branch: master
Commit: 1b68d4e7cec5b6d79b3811a34f59c3790d5a5e6a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1b68d4e7cec5b6d79b3811a34f59c3790d5a5e6a

Author: Eric Pouech <eric.pouech at orange.fr>
Date:   Thu Apr  1 21:24:20 2010 +0200

dbghelp: Extend dwarf stack unwinding by reading information out of .debug_frame sections.

Implement dwarf stack unwinding for i386 CPU.

---

 dlls/dbghelp/cpu_i386.c |   31 +++++++++++++++++++++++++++++++
 dlls/dbghelp/dwarf.c    |   24 +++++++++++++++++-------
 2 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/dlls/dbghelp/cpu_i386.c b/dlls/dbghelp/cpu_i386.c
index 7a951f7..dc00410 100644
--- a/dlls/dbghelp/cpu_i386.c
+++ b/dlls/dbghelp/cpu_i386.c
@@ -107,6 +107,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
     DWORD               p;
     WORD                val;
     BOOL                do_switch;
+    unsigned            deltapc = 1;
 
     /* sanity check */
     if (curr_mode >= stm_done) return FALSE;
@@ -132,6 +133,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
 
         /* Init done */
         curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit;
+        deltapc = 0;
 
         /* cur_switch holds address of WOW32Reserved field in TEB in debuggee
          * address space
@@ -191,6 +193,21 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
          * we will get it in the next frame
          */
         memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
+#ifdef __i386__
+        if (curr_mode == stm_32bit)
+        {
+            DWORD_PTR       xframe;
+
+            if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &xframe))
+            {
+                frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
+                frame->AddrStack.Offset = context->Esp = xframe;
+                frame->AddrFrame.Offset = context->Ebp;
+                frame->AddrReturn.Offset = context->Eip;
+                goto done_pep;
+            }
+        }
+#endif
     }
     else
     {
@@ -317,6 +334,18 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
             }
             else
             {
+#ifdef __i386__
+                DWORD_PTR       xframe;
+
+                if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &xframe))
+                {
+                    frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
+                    frame->AddrStack.Offset = context->Esp = xframe;
+                    frame->AddrFrame.Offset = context->Ebp;
+                    frame->AddrReturn.Offset = context->Eip;
+                    goto done_pep;
+                }
+#endif
                 frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
                 /* "pop up" previous EBP value */
                 if (!sw_read_mem(csw, frame->AddrFrame.Offset,
@@ -381,6 +410,8 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
         sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
                     frame->Params, sizeof(frame->Params));
     }
+    goto done_pep; /* just to ensure done_pep label is referenced */
+done_pep:
 
     frame->Far = TRUE;
     frame->Virtual = TRUE;
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index 78860d7..68e322c 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -2403,14 +2403,17 @@ static BOOL parse_cie_details(dwarf2_traverse_context_t* ctx, struct frame_info*
 
 static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR delta,
                            dwarf2_traverse_context_t* fde_ctx, dwarf2_traverse_context_t* cie_ctx,
-                           struct frame_info* info)
+                           struct frame_info* info, BOOL in_eh_frame)
 {
     const unsigned char*        ptr_blk;
     const unsigned char*        cie_ptr;
     const unsigned char*        last_cie_ptr = (const unsigned char*)~0;
     unsigned                    len, id;
     unsigned long               start, range;
+    unsigned                    cie_id;
+    const BYTE*                 start_data = fde_ctx->data;
 
+    cie_id = in_eh_frame ? 0 : DW_CIE_ID;
     for (; fde_ctx->data + 2 * 4 < fde_ctx->end_data; fde_ctx->data = ptr_blk)
     {
         /* find the FDE for address addr (skip CIE) */
@@ -2418,7 +2421,7 @@ static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR
         if (len == 0xffffffff) FIXME("Unsupported yet 64-bit CIEs\n");
         ptr_blk = fde_ctx->data + len;
         id  = dwarf2_parse_u4(fde_ctx);
-        if (id == 0) /* FIXME DW_CIE_ID */
+        if (id == cie_id)
         {
             last_cie_ptr = fde_ctx->data - 8;
             /* we need some bits out of the CIE in order to parse all contents */
@@ -2428,7 +2431,7 @@ static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR
             cie_ctx->word_size = fde_ctx->word_size;
             continue;
         }
-        cie_ptr = fde_ctx->data - id - 4;
+        cie_ptr = (in_eh_frame) ? fde_ctx->data - id - 4 : start_data + id;
         if (cie_ptr != last_cie_ptr)
         {
             last_cie_ptr = cie_ptr;
@@ -2436,7 +2439,7 @@ static BOOL dwarf2_get_cie(unsigned long addr, struct module* module, DWORD_PTR
             cie_ctx->word_size = fde_ctx->word_size;
             cie_ctx->end_data = cie_ptr + 4;
             cie_ctx->end_data = cie_ptr + 4 + dwarf2_parse_u4(cie_ctx);
-            if (dwarf2_parse_u4(cie_ctx) != 0) /* FIXME DW_CIE_ID */
+            if (dwarf2_parse_u4(cie_ctx) != cie_id)
             {
                 FIXME("wrong CIE pointer\n");
                 return FALSE;
@@ -2925,10 +2928,17 @@ BOOL dwarf2_virtual_unwind(struct cpu_stack_walk* csw, ULONG_PTR ip, CONTEXT* co
      */
     delta = pair.effective->module.BaseOfImage + modfmt->u.dwarf2_info->eh_frame.rva -
         (DWORD_PTR)modfmt->u.dwarf2_info->eh_frame.address;
-    if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info))
+    if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info, TRUE))
     {
-        TRACE("Couldn't find information for %lx\n", ip);
-        return FALSE;
+        fde_ctx.data = modfmt->u.dwarf2_info->debug_frame.address;
+        fde_ctx.end_data = fde_ctx.data + modfmt->u.dwarf2_info->debug_frame.size;
+        fde_ctx.word_size = modfmt->u.dwarf2_info->word_size;
+        delta = pair.effective->reloc_delta;
+        if (!dwarf2_get_cie(ip, pair.effective, delta, &fde_ctx, &cie_ctx, &info, FALSE))
+        {
+            TRACE("Couldn't find information for %lx\n", ip);
+            return FALSE;
+        }
     }
 
     TRACE("function %lx/%lx code_align %lu data_align %ld retaddr %s\n",




More information about the wine-cvs mailing list