[PATCH 22/31] [DbgHelp]: dwarf & func block

Eric Pouech eric.pouech at wanadoo.fr
Sun Jun 18 14:32:03 CDT 2006


- properly handling functions' block
- handling of variables inside of blocks (either on stack,
  or in a register, or relative to the frame register if any)
- added dwarf2_subprogram_t structure so that
  we can pass around relevant information for
  function parsing

A+
---

 dlls/dbghelp/dwarf.c |  201 ++++++++++++++++++++++++++++++++------------------
 1 files changed, 127 insertions(+), 74 deletions(-)

diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c
index 280e51d..8f4ec4e 100644
--- a/dlls/dbghelp/dwarf.c
+++ b/dlls/dbghelp/dwarf.c
@@ -55,11 +55,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_dwarf
 
 /* FIXME:
  * - Functions:
- *      o local variables
  *      o unspecified parameters
  *      o inlined functions
  *      o line numbers
  *      o Debug{Start|End}Point
+ *      o CFA
  * - Udt
  *      o proper types loading (addresses, bitfield, nesting)
  */
@@ -941,30 +941,15 @@ static struct symt* dwarf2_parse_enumera
     return di->symt;
 }
 
-static void dwarf2_parse_variable(dwarf2_parse_context_t* ctx,
-				  dwarf2_debug_info_t* di)
-{
-    struct symt* var_type;
-    union attribute name;
-
-    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
-
-    var_type = dwarf2_lookup_type(ctx, di);
-    dwarf2_find_name(ctx, di, &name, "variable");
-    /* FIXME: still lots to do !!! */
-
-    if (di->abbrev->have_child) FIXME("Unsupported children\n");
-}
-
 static unsigned dwarf2_map_register(int regno)
 {
     unsigned    reg;
 
     switch (regno)
     {
-    case -1:
+    case Wine_DW_no_register: FIXME("What the heck\n"); reg = 0; break;
     /* FIXME: this is a dirty hack */
-    case -2: reg = 0;          break;
+    case Wine_DW_frame_register: reg = 0;          break;
     case  0: reg = CV_REG_EAX; break;
     case  1: reg = CV_REG_ECX; break;
     case  2: reg = CV_REG_EDX; break;
@@ -1005,63 +990,101 @@ reg: fop   31
     return reg;
 }
 
-static void dwarf2_parse_subprogram_parameter(dwarf2_parse_context_t* ctx,
-                                              struct symt_function* func,
-					      struct symt_block* block,
-					      dwarf2_debug_info_t* di)
+/* structure used to pass information around when parsing a subprogram */
+typedef struct dwarf2_subprogram_s
+{
+    dwarf2_parse_context_t*     ctx;
+    struct symt_compiland*      compiland;
+    struct symt_function*       func;
+    long                        frame_offset;
+    int                         frame_reg;
+} dwarf2_subprogram_t;
+
+/******************************************************************
+ *		dwarf2_parse_variable
+ *
+ * Parses any variable (parameter, local/global variable)
+ */
+static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
+                                  struct symt_block* block,
+                                  dwarf2_debug_info_t* di)
 {
     struct symt* param_type;
     union attribute loc;
+    BOOL is_pmt = di->abbrev->tag == DW_TAG_formal_parameter;
 
-    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
 
-    param_type = dwarf2_lookup_type(ctx, di);
+    param_type = dwarf2_lookup_type(subpgm->ctx, di);
     if (dwarf2_find_attribute(di, DW_AT_location, &loc))
     {
         union attribute name;
-        unsigned long offset;
+        union attribute ext;
+        long offset;
         int in_reg;
 
-        dwarf2_find_name(ctx, di, &name, "parameter");
-        offset = dwarf2_compute_location(ctx, loc.block, &in_reg);
+        dwarf2_find_name(subpgm->ctx, di, &name, "parameter");
+        offset = dwarf2_compute_location(subpgm->ctx, loc.block, &in_reg);
 	TRACE("found parameter %s/%ld (reg=%d) at %s\n",
-              name.string, offset, in_reg, dwarf2_debug_ctx(ctx));
-        symt_add_func_local(ctx->module, func, 
-                            DataIsParam, dwarf2_map_register(in_reg), offset,
-                            block, param_type, name.string);
+              name.string, offset, in_reg, dwarf2_debug_ctx(subpgm->ctx));
+        switch (in_reg)
+        {
+        case Wine_DW_no_register:
+            /* it's a global variable */
+            /* FIXME: we don't handle it's scope yet */
+            if (!dwarf2_find_attribute(di, DW_AT_external, &ext))
+                ext.uvalue = 0;
+            symt_new_global_variable(subpgm->ctx->module, subpgm->compiland,
+                                     name.string, !ext.uvalue,
+                                     subpgm->ctx->module->module.BaseOfImage + offset,
+                                     0, param_type);
+            break;
+        case Wine_DW_frame_register:
+            in_reg = subpgm->frame_reg;
+            offset += subpgm->frame_offset;
+            /* fall through */
+        default:
+            /* either a pmt/variable relative to frame pointer or
+             * pmt/variable in a register
+             */
+            symt_add_func_local(subpgm->ctx->module, subpgm->func, 
+                                is_pmt ? DataIsParam : DataIsLocal,
+                                dwarf2_map_register(in_reg), offset,
+                                block, param_type, name.string);
+            break;
+        }
     }
-    if (func && func->type)
-        symt_add_function_signature_parameter(ctx->module,
-                                              (struct symt_func_signature*)func->type,
+    if (is_pmt && subpgm->func && subpgm->func->type)
+        symt_add_function_signature_parameter(subpgm->ctx->module,
+                                              (struct symt_func_signature*)subpgm->func->type,
                                               param_type);
 
     if (di->abbrev->have_child) FIXME("Unsupported children\n");
 }
 
-static void dwarf2_parse_subprogram_label(dwarf2_parse_context_t* ctx,
-                                          struct symt_function* func,
+static void dwarf2_parse_subprogram_label(dwarf2_subprogram_t* subpgm,
                                           dwarf2_debug_info_t* di)
 {
     union attribute name;
     union attribute low_pc;
 
-    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
 
     if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc)) low_pc.uvalue = 0;
-    dwarf2_find_name(ctx, di, &name, "label");
+    dwarf2_find_name(subpgm->ctx, di, &name, "label");
 
-    symt_add_function_point(ctx->module, func, SymTagLabel,
-                            ctx->module->module.BaseOfImage + low_pc.uvalue, name.string);
+    symt_add_function_point(subpgm->ctx->module, subpgm->func, SymTagLabel,
+                            subpgm->ctx->module->module.BaseOfImage + low_pc.uvalue, name.string);
 }
 
-static void dwarf2_parse_subprogram_block(dwarf2_parse_context_t* ctx, 
-					  dwarf2_debug_info_t* di, 
-					  struct symt_function* func);
+static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
+                                          struct symt_block* block_parent,
+					  dwarf2_debug_info_t* di);
 
-static void dwarf2_parse_inlined_subroutine(dwarf2_parse_context_t* ctx,
+static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
                                             dwarf2_debug_info_t* di)
 {
-    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
 
     /* FIXME: attributes to handle:
        DW_AT_low_pc:
@@ -1086,7 +1109,9 @@ static void dwarf2_parse_inlined_subrout
                  */
                 break;
             case DW_TAG_variable:
-                dwarf2_parse_variable(ctx, child);
+                /* FIXME:
+                 * dwarf2_parse_variable(ctx, child);
+                 */
                 break;
             case DW_TAG_lexical_block:
                 /* FIXME:
@@ -1095,28 +1120,35 @@ static void dwarf2_parse_inlined_subrout
                 break;
             case DW_TAG_inlined_subroutine:
                 /* FIXME */
-                dwarf2_parse_inlined_subroutine(ctx, child);
+                dwarf2_parse_inlined_subroutine(subpgm, child);
                 break;
             case DW_TAG_label:
-                /* FIXME
-                 * dwarf2_parse_subprogram_label(ctx, func, child);
-                 */
+                dwarf2_parse_subprogram_label(subpgm, child);
                 break;
             default:
                 FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
-                      child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+                      child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx),
+                      dwarf2_debug_di(di));
             }
         }
     }
 }
 
-static void dwarf2_parse_subprogram_block(dwarf2_parse_context_t* ctx, 
-					  dwarf2_debug_info_t* di, 
-					  struct symt_function* func)
+static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm, 
+                                          struct symt_block* parent_block,
+					  dwarf2_debug_info_t* di)
 {
-    TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+    struct symt_block*  block;
+    union attribute     low_pc;
+    union attribute     high_pc;
 
-    /* if (!dwarf2_find_attribute(di, DW_AT_ranges, ??)): what to do ? */
+    TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
+
+    if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc)) low_pc.uvalue = 0;
+    if (!dwarf2_find_attribute(di, DW_AT_high_pc, &high_pc)) high_pc.uvalue = 0;
+
+    block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
+                                 low_pc.uvalue, high_pc.uvalue - low_pc.uvalue);
 
     if (di->abbrev->have_child) /** any interest to not have child ? */
     {
@@ -1130,19 +1162,24 @@ static void dwarf2_parse_subprogram_bloc
             switch (child->abbrev->tag)
             {
             case DW_TAG_inlined_subroutine:
-                dwarf2_parse_inlined_subroutine(ctx, child);
+                dwarf2_parse_inlined_subroutine(subpgm, child);
                 break;
             case DW_TAG_variable:
-                dwarf2_parse_variable(ctx, child);
+                dwarf2_parse_variable(subpgm, block, child);
                 break;
             case DW_TAG_lexical_block:
-                dwarf2_parse_subprogram_block(ctx, child, func);
+                dwarf2_parse_subprogram_block(subpgm, block, child);
                 break;
             case DW_TAG_subprogram:
                 /* FIXME: likely a declaration (to be checked)
                  * skip it for now
                  */
                 break;
+            case DW_TAG_formal_parameter:
+                /* FIXME: likely elements for exception handling (GCC flavor)
+                 * Skip it for now
+                 */
+                break;
             case DW_TAG_class_type:
             case DW_TAG_structure_type:
             case DW_TAG_union_type:
@@ -1151,10 +1188,12 @@ static void dwarf2_parse_subprogram_bloc
                 break;
             default:
                 FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
-                      child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
+                      child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
             }
         }
     }
+
+    symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
 }
 
 static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
@@ -1166,9 +1205,10 @@ static struct symt* dwarf2_parse_subprog
     union attribute high_pc;
     union attribute is_decl;
     union attribute inline_flags;
+    union attribute frame;
     struct symt* ret_type;
-    struct symt_function* func = NULL;
     struct symt_function_signature* sig_type;
+    dwarf2_subprogram_t subpgm;
 
     if (di->symt) return di->symt;
 
@@ -1185,12 +1225,27 @@ static struct symt* dwarf2_parse_subprog
     sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C);
     if (!is_decl.uvalue)
     {
-        func = symt_new_function(ctx->module, compiland, name.string,
-                                 ctx->module->module.BaseOfImage + low_pc.uvalue,
-                                 high_pc.uvalue - low_pc.uvalue,
-                                 &sig_type->symt);
-        di->symt = &func->symt;
+        subpgm.func = symt_new_function(ctx->module, compiland, name.string,
+                                        ctx->module->module.BaseOfImage + low_pc.uvalue,
+                                        high_pc.uvalue - low_pc.uvalue,
+                                        &sig_type->symt);
+        di->symt = &subpgm.func->symt;
+    }
+    else subpgm.func = NULL;
+
+    subpgm.ctx = ctx;
+    subpgm.compiland = compiland;
+    if (dwarf2_find_attribute(di, DW_AT_frame_base, &frame))
+    {
+        subpgm.frame_offset = dwarf2_compute_location(ctx, frame.block, &subpgm.frame_reg);
+        TRACE("For %s got %ld/%d\n", name.string, subpgm.frame_offset, subpgm.frame_reg);
     }
+    else /* on stack !! */
+    {
+        subpgm.frame_reg = 0;
+        subpgm.frame_offset = 0;
+    }
+
     if (di->abbrev->have_child) /** any interest to not have child ? */
     {
         dwarf2_debug_info_t**   pchild = NULL;
@@ -1202,17 +1257,15 @@ static struct symt* dwarf2_parse_subprog
 
             switch (child->abbrev->tag)
             {
+            case DW_TAG_variable:
             case DW_TAG_formal_parameter:
-                dwarf2_parse_subprogram_parameter(ctx, func, NULL, child);
+                dwarf2_parse_variable(&subpgm, NULL, child);
                 break;
             case DW_TAG_lexical_block:
-                dwarf2_parse_subprogram_block(ctx, child, func);
-                break;
-            case DW_TAG_variable:
-                dwarf2_parse_variable(ctx, child);
+                dwarf2_parse_subprogram_block(&subpgm, NULL, child);
                 break;
             case DW_TAG_inlined_subroutine:
-                dwarf2_parse_inlined_subroutine(ctx, child);
+                dwarf2_parse_inlined_subroutine(&subpgm, child);
                 break;
             case DW_TAG_subprogram:
                 /* FIXME: likely a declaration (to be checked)
@@ -1220,7 +1273,7 @@ static struct symt* dwarf2_parse_subprog
                  */
                 break;
             case DW_TAG_label:
-                dwarf2_parse_subprogram_label(ctx, func, child);
+                dwarf2_parse_subprogram_label(&subpgm, child);
                 break;
             case DW_TAG_class_type:
             case DW_TAG_structure_type:
@@ -1239,7 +1292,7 @@ static struct symt* dwarf2_parse_subprog
 	}
     }
 
-    symt_normalize_function(ctx->module, func);
+    symt_normalize_function(subpgm.ctx->module, subpgm.func);
 
     return di->symt;
 }



More information about the wine-patches mailing list