Eric Pouech : dbghelp: Add ability to add a SymTagCustom element to a function.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Nov 27 12:51:56 CST 2006


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

Author: Eric Pouech <eric.pouech at wanadoo.fr>
Date:   Fri Nov 24 22:17:59 2006 +0100

dbghelp: Add ability to add a SymTagCustom element to a function.

Make use of it to store the frame information for a dwarf function
(either because frame's location is a location list, or because one of
the function's variables is not properly computed at parse time).

---

 dlls/dbghelp/dwarf.c |  160 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 148 insertions(+), 12 deletions(-)

diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index f99c844..b8b05c4 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -624,8 +624,9 @@ reg: fop   31
     return reg;
 }
 
-static BOOL compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
-                             const struct location* frame)
+static enum location_error
+compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
+                 const struct location* frame)
 {
     unsigned long stack[64];
     unsigned stk;
@@ -721,11 +722,11 @@ static BOOL compute_location(dwarf2_trav
             break;
         default:
             FIXME("Unhandled attr op: %x\n", op);
-            return FALSE;
+            return loc_err_internal;
         }
     }
     loc->offset = stack[stk];
-    return TRUE;
+    return 0;
 }
 
 static BOOL dwarf2_compute_location_attr(dwarf2_parse_context_t* ctx,
@@ -757,16 +758,18 @@ static BOOL dwarf2_compute_location_attr
 
     if (xloc.u.block.size)
     {
-        dwarf2_traverse_context_t  lctx;
+        dwarf2_traverse_context_t       lctx;
+        enum location_error             err;
 
         lctx.data = xloc.u.block.ptr;
         lctx.end_data = xloc.u.block.ptr + xloc.u.block.size;
         lctx.word_size = ctx->word_size;
 
-        if (!compute_location(&lctx, loc, frame))
+        err = compute_location(&lctx, loc, frame);
+        if (err < 0)
         {
             loc->kind = loc_error;
-            loc->reg = loc_err_too_complex;
+            loc->reg = err;
         }
         else if (loc->kind == loc_dwarf2_block)
         {
@@ -1201,6 +1204,7 @@ typedef struct dwarf2_subprogram_s
     dwarf2_parse_context_t*     ctx;
     struct symt_compiland*      compiland;
     struct symt_function*       func;
+    BOOL                        non_computed_variable;
     struct location             frame;
 } dwarf2_subprogram_t;
 
@@ -1235,7 +1239,7 @@ static void dwarf2_parse_variable(dwarf2
         {
         case loc_absolute:
             /* it's a global variable */
-            /* FIXME: we don't handle it's scope yet */
+            /* FIXME: we don't handle its scope yet */
             if (!dwarf2_find_attribute(subpgm->ctx, di, DW_AT_external, &ext))
                 ext.u.uvalue = 0;
             symt_new_global_variable(subpgm->ctx->module, subpgm->compiland,
@@ -1244,6 +1248,7 @@ static void dwarf2_parse_variable(dwarf2
                                      0, param_type);
             break;
         default:
+            subpgm->non_computed_variable = TRUE;
             /* fall through */
         case loc_register:
         case loc_regrel:
@@ -1459,6 +1464,7 @@ static struct symt* dwarf2_parse_subprog
         subpgm.frame.reg = 0;
         subpgm.frame.offset = 0;
     }
+    subpgm.non_computed_variable = FALSE;
 
     if (di->abbrev->have_child) /** any interest to not have child ? */
     {
@@ -1506,6 +1512,11 @@ static struct symt* dwarf2_parse_subprog
 	}
     }
 
+    if (subpgm.non_computed_variable || subpgm.frame.kind >= loc_user)
+    {
+        symt_add_function_point(ctx->module, subpgm.func, SymTagCustom,
+                                &subpgm.frame, NULL);
+    }
     symt_normalize_function(subpgm.ctx->module, subpgm.func);
 
     return di->symt;
@@ -1893,15 +1904,140 @@ static BOOL dwarf2_parse_compilation_uni
     return ret;
 }
 
+static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start,
+                                  unsigned long ip,
+                                  dwarf2_traverse_context_t*  lctx)
+{
+    DWORD                       beg, end;
+    const BYTE*                 ptr = start;
+    DWORD                       len;
+
+    while (ptr < module->dwarf2_info->debug_loc.address + module->dwarf2_info->debug_loc.size)
+    {
+        beg = dwarf2_get_u4(ptr); ptr += 4;
+        end = dwarf2_get_u4(ptr); ptr += 4;
+        if (!beg && !end) break;
+        len = dwarf2_get_u2(ptr); ptr += 2;
+
+        if (beg <= ip && ip < end)
+        {
+            lctx->data = ptr;
+            lctx->end_data = ptr + len;
+            lctx->word_size = 4; /* FIXME word size !!! */
+            return TRUE;
+        }
+        ptr += len;
+    }
+    WARN("Couldn't find ip in location list\n");
+    return FALSE;
+}
+
+static enum location_error loc_compute_frame(const struct module* module,
+                                             const struct symt_function* func,
+                                             DWORD ip, struct location* frame)
+{
+    struct symt**               psym = NULL;
+    struct location*            pframe;
+    dwarf2_traverse_context_t   lctx;
+    enum location_error         err;
+
+    while ((psym = vector_iter_up(&func->vchildren, psym)))
+    {
+        if ((*psym)->tag == SymTagCustom)
+        {
+            pframe = &((struct symt_function_point*)*psym)->loc;
+
+            /* First, recompute the frame information, if needed */
+            switch (pframe->kind)
+            {
+            case loc_regrel:
+            case loc_register:
+                *frame = *pframe;
+                break;
+            case loc_dwarf2_location_list:
+                WARN("Searching loclist for %s\n", func->hash_elt.name);
+                if (!dwarf2_lookup_loclist(module, 
+                                           module->dwarf2_info->debug_loc.address + pframe->offset,
+                                           ip, &lctx))
+                    return loc_err_out_of_scope;
+                if ((err = compute_location(&lctx, frame, NULL)) < 0) return err;
+                if (frame->kind >= loc_user)
+                {
+                    WARN("Couldn't compute runtime frame location\n");
+                    return loc_err_too_complex;
+                }
+                break;
+            default:
+                WARN("Unsupported frame kind %d\n", pframe->kind);
+                return loc_err_internal;
+            }
+            return 0;
+        }
+    }
+    WARN("Couldn't find Custom function point, whilst location list offset is searched\n");
+    return loc_err_internal;
+}
+
 static void dwarf2_location_compute(struct process* pcs,
                                     const struct module* module,
                                     const struct symt_function* func,
                                     struct location* loc)
 {
-    FIXME("Not implemented yet\n");
-    loc->kind = loc_register;
-    loc->reg = -1;
-    loc->offset = 0;
+    struct location             frame;
+    DWORD                       ip;
+    int                         err;
+    dwarf2_traverse_context_t   lctx;
+
+    if (!func->container || func->container->tag != SymTagCompiland)
+    {
+        WARN("We'd expect function %s's container to exist and be a compiland\n", func->hash_elt.name);
+        err = loc_err_internal;
+    }
+    else
+    {
+        /* instruction pointer relative to compiland's start */
+        ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address;
+
+        if ((err = loc_compute_frame(module, func, ip, &frame)) == 0)
+        {
+            switch (loc->kind)
+            {
+            case loc_dwarf2_location_list:
+                /* Then, if the variable has a location list, find it !! */
+                if (dwarf2_lookup_loclist(module, 
+                                          module->dwarf2_info->debug_loc.address + loc->offset,
+                                          ip, &lctx))
+                    goto do_compute;
+                err = loc_err_out_of_scope;
+                break;
+            case loc_dwarf2_block:
+                /* or if we have a copy of an existing block, get ready for it */
+                {
+                    unsigned*   ptr = (unsigned*)loc->offset;
+
+                    lctx.data = (const BYTE*)(ptr + 1);
+                    lctx.end_data = lctx.data + *ptr;
+                    lctx.word_size = 4; /* FIXME !! */
+                }
+            do_compute:
+                /* now get the variable */
+                err = compute_location(&lctx, loc, &frame);
+                break;
+            case loc_register:
+            case loc_regrel:
+                /* nothing to do */
+                break;
+            default:
+                WARN("Unsupported local kind %d\n", loc->kind);
+                err = loc_err_internal;
+            }
+        }
+    }
+    if (err < 0)
+    {
+        loc->kind = loc_register;
+        loc->reg = err;
+    }
 }
 
 BOOL dwarf2_parse(struct module* module, unsigned long load_offset,




More information about the wine-cvs mailing list