[PATCH 11/13] [DbgHelp]: MSC forward declaration

Eric Pouech eric.pouech at wanadoo.fr
Sat Mar 18 06:33:11 CST 2006


- create an infrastructure for handling forward usage
  of type records
- used it in some cases (pointer to yet not defined udt,
  function signature, modifiers)

A+
---

 dlls/dbghelp/msc.c |  333 +++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 226 insertions(+), 107 deletions(-)

diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index d586eb4..4513d8c 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -355,7 +355,11 @@ static int codeview_add_type(unsigned in
 
         if (cv_current_module->defined_types == NULL) return FALSE;
     }
-
+    if (cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE])
+    {
+        if (cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE] != dt)
+            FIXME("Overwritting at %x\n", typeno);
+    }
     cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE] = dt;
     return TRUE;
 }
@@ -375,21 +379,63 @@ static void codeview_clear_type_table(vo
     cv_current_module = NULL;
 }
 
-static struct symt* codeview_add_type_pointer(struct module* module,
-                                              unsigned int datatype)
+static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp,
+                                            unsigned curr_type,
+                                            const union codeview_type* type, BOOL details);
+
+static void* codeview_cast_symt(struct symt* symt, enum SymTagEnum tag)
+{
+    if (symt->tag != tag)
+    {
+        FIXME("Bad tag. Expected %d, but got %d\n", tag, symt->tag);
+        return NULL;
+    }   
+    return symt;
+}
+
+static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp,
+                                        unsigned typeno)
 {
-    return &symt_new_pointer(module,
-                             codeview_get_type(datatype, FALSE))->symt;
+    struct symt*                symt;
+    const union codeview_type*  p;
+
+    if (!typeno) return NULL;
+    if ((symt = codeview_get_type(typeno, TRUE))) return symt;
+
+    /* forward declaration */
+    if (!(p = codeview_jump_to_type(ctp, typeno)))
+    {
+        FIXME("Cannot locate type %x\n", typeno);
+        return NULL;
+    }
+    symt = codeview_parse_one_type(ctp, typeno, p, FALSE);
+    if (!symt) FIXME("Couldn't load forward type %x\n", typeno);
+    return symt;
 }
 
-static struct symt* codeview_add_type_array(struct module* module, 
+static struct symt* codeview_add_type_pointer(struct codeview_type_parse* ctp,
+                                              struct symt* existing,
+                                              unsigned int pointee_type)
+{
+    struct symt* pointee;
+
+    if (existing)
+    {
+        existing = codeview_cast_symt(existing, SymTagPointerType);
+        return existing;
+    }
+    pointee = codeview_fetch_type(ctp, pointee_type);
+    return &symt_new_pointer(ctp->module, pointee)->symt;
+}
+
+static struct symt* codeview_add_type_array(struct codeview_type_parse* ctp, 
                                             const char* name,
                                             unsigned int elemtype,
                                             unsigned int indextype,
                                             unsigned int arr_len)
 {
-    struct symt*        elem = codeview_get_type(elemtype, FALSE);
-    struct symt*        index = codeview_get_type(indextype, FALSE);
+    struct symt*        elem = codeview_fetch_type(ctp, elemtype);
+    struct symt*        index = codeview_fetch_type(ctp, indextype);
     DWORD               arr_max = 0;
 
     if (elem)
@@ -398,7 +444,7 @@ static struct symt* codeview_add_type_ar
         symt_get_info(elem, TI_GET_LENGTH, &elem_size);
         if (elem_size) arr_max = arr_len / (DWORD)elem_size;
     }
-    return &symt_new_array(module, 0, arr_max, elem, index)->symt;
+    return &symt_new_array(ctp->module, 0, arr_max, elem, index)->symt;
 }
 
 static int codeview_add_type_enum_field_list(struct module* module,
@@ -450,54 +496,57 @@ static int codeview_add_type_enum_field_
 
 static void codeview_add_udt_element(struct codeview_type_parse* ctp,
                                      struct symt_udt* symt, const char* name,
-                                     int value, DWORD type)
+                                     int value, unsigned type)
 {
     struct symt*                subtype;
     const union codeview_reftype*cv_type;
 
-    subtype = codeview_get_type(type, FALSE);
-
-    /* FIXME: we expect no forward usage of subtypes */
-    if (subtype)
-    {
-        DWORD64 elem_size = 0;
-        symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
-        symt_add_udt_element(ctp->module, symt, name, subtype,
-                             value << 3, (DWORD)elem_size << 3);
-    }
-    else if ((cv_type = codeview_jump_to_type(ctp, type)))
+    if ((cv_type = codeview_jump_to_type(ctp, type)))
     {
         switch (cv_type->generic.id)
         {
         case LF_BITFIELD_V1:
             symt_add_udt_element(ctp->module, symt, name,
-                                 codeview_get_type(cv_type->bitfield_v1.type, FALSE),
+                                 codeview_fetch_type(ctp, cv_type->bitfield_v1.type),
                                  cv_type->bitfield_v1.bitoff,
                                  cv_type->bitfield_v1.nbits);
-            break;
+            return;
         case LF_BITFIELD_V2:
             symt_add_udt_element(ctp->module, symt, name,
-                                 codeview_get_type(cv_type->bitfield_v2.type, FALSE),
+                                 codeview_fetch_type(ctp, cv_type->bitfield_v2.type),
                                  cv_type->bitfield_v2.bitoff,
                                  cv_type->bitfield_v2.nbits);
-            break;
-        default:
-            FIXME("Unexpected leaf %x\n", cv_type->generic.id);
+            return;
         }
     }
+    subtype = codeview_fetch_type(ctp, type);
+
+    if (subtype)
+    {
+        DWORD64 elem_size = 0;
+        symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
+        symt_add_udt_element(ctp->module, symt, name, subtype,
+                             value << 3, (DWORD)elem_size << 3);
+    }
 }
 
 static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp,
                                                struct symt_udt* symt,
-                                               const union codeview_reftype* ref_type)
+                                               unsigned fieldlistno)
 {
-    const unsigned char*        ptr = ref_type->fieldlist.list;
-    const unsigned char*        last = (const BYTE*)ref_type + ref_type->generic.len + 2;
+    const unsigned char*        ptr;
+    const unsigned char*        last;
     int                         value, leaf_len;
     const struct p_string*      p_name;
     const char*                 c_name;
+    const union codeview_reftype*type_ref;
     const union codeview_fieldtype* type;
 
+    if (!fieldlistno) return TRUE;
+    type_ref = codeview_jump_to_type(ctp, fieldlistno);
+    ptr = type_ref->fieldlist.list;
+    last = (const BYTE*)type_ref + type_ref->generic.len + 2;
+
     while (ptr < last)
     {
         if (*ptr >= 0xf0)       /* LF_PAD... */
@@ -662,28 +711,50 @@ static int codeview_add_type_struct_fiel
     return TRUE;
 }
 
-static struct symt* codeview_add_type_enum(struct module* module,
+static struct symt* codeview_add_type_enum(struct codeview_type_parse* ctp,
+                                           struct symt* existing,
                                            const char* name,
-                                           const union codeview_reftype* fieldlist)
+                                           unsigned fieldlistno)
 {
-    struct symt_enum*   symt = symt_new_enum(module, name);
+    struct symt_enum*   symt;
 
-    if (fieldlist) codeview_add_type_enum_field_list(module, symt, fieldlist);
+    if (existing)
+    {
+        if (!(symt = codeview_cast_symt(existing, SymTagEnum))) return NULL;
+        /* should also check that all fields are the same */
+    }
+    else
+    {
+        symt = symt_new_enum(ctp->module, name);
+        if (fieldlistno)
+        {
+            const union codeview_reftype* fieldlist;
+            fieldlist = codeview_jump_to_type(ctp, fieldlistno);
+            codeview_add_type_enum_field_list(ctp->module, symt, fieldlist);
+        }
+    }
     return &symt->symt;
 }
 
 static struct symt* codeview_add_type_struct(struct codeview_type_parse* ctp,
+                                             struct symt* existing,
                                              const char* name, int structlen, 
-                                             const union codeview_reftype* fieldlist,
                                              enum UdtKind kind)
 {
-    struct symt_udt*    symt = symt_new_udt(ctp->module, name, structlen, kind);
+    struct symt_udt*    symt;
+
+    if (existing)
+    {
+        if (!(symt = codeview_cast_symt(existing, SymTagUDT))) return NULL;
+        /* should also check that all fields are the same */
+    }
+    else symt = symt_new_udt(ctp->module, name, structlen, kind);
 
-    if (fieldlist) codeview_add_type_struct_field_list(ctp, symt, fieldlist);
     return &symt->symt;
 }
 
-static struct symt* codeview_add_func_signature(struct codeview_type_parse* ctp, 
+static struct symt* codeview_new_func_signature(struct codeview_type_parse* ctp, 
+                                                struct symt* existing,
                                                 unsigned ret_type,
                                                 unsigned args_list,
                                                 enum CV_call_e call_conv)
@@ -691,10 +762,18 @@ static struct symt* codeview_add_func_si
     struct symt_function_signature*     sym;
     const union codeview_reftype*       reftype;
 
-    sym = symt_new_function_signature(ctp->module, codeview_get_type(ret_type, FALSE),
-                                      call_conv);
-    reftype = codeview_jump_to_type(ctp, args_list);
-    if (reftype)
+    if (existing)
+    {
+        sym = codeview_cast_symt(existing, SymTagFunctionType);
+        if (!sym) return NULL;
+    }
+    else
+    {
+        sym = symt_new_function_signature(ctp->module, 
+                                          codeview_fetch_type(ctp, ret_type),
+                                          call_conv);
+    }
+    if (args_list && (reftype = codeview_jump_to_type(ctp, args_list)))
     {
         int i;
         switch (reftype->generic.id)
@@ -702,14 +781,12 @@ static struct symt* codeview_add_func_si
         case LF_ARGLIST_V1:
             for (i = 0; i < reftype->arglist_v1.num; i++)
                 symt_add_function_signature_parameter(ctp->module, sym,
-                                                      codeview_get_type(reftype->arglist_v1.args[i],
-                                                                        FALSE));
+                                                      codeview_fetch_type(ctp, reftype->arglist_v1.args[i]));
             break;
         case LF_ARGLIST_V2:
             for (i = 0; i < reftype->arglist_v2.num; i++)
                 symt_add_function_signature_parameter(ctp->module, sym,
-                                                      codeview_get_type(reftype->arglist_v2.args[i],
-                                                                        FALSE));
+                                                      codeview_fetch_type(ctp, reftype->arglist_v2.args[i]));
             break;
         default:
             FIXME("Unexpected leaf %x for signature's pmt\n", reftype->generic.id);
@@ -721,13 +798,15 @@ static struct symt* codeview_add_func_si
 
 static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp,
                                             unsigned curr_type,
-                                            const union codeview_type* type)
+                                            const union codeview_type* type, BOOL details)
 {
-    const union codeview_reftype*type_ref;
+    struct symt*                symt;
     int                         value, leaf_len;
     const struct p_string*      p_name;
     const char*                 c_name;
-    struct symt*                symt;
+    struct symt*                existing;
+
+    existing = codeview_get_type(curr_type, TRUE);
 
     switch (type->generic.id)
     {
@@ -741,7 +820,9 @@ static struct symt* codeview_parse_one_t
              type->modifier_v1.attribute & 0x02 ? "volatile " : "",
              type->modifier_v1.attribute & 0x04 ? "unaligned " : "",
              type->modifier_v1.attribute & ~0x07 ? "unknown " : "");
-        symt = codeview_get_type(type->modifier_v1.type, FALSE);
+        if (!(symt = codeview_get_type(type->modifier_v1.type, TRUE)))
+            symt = codeview_parse_one_type(ctp, type->modifier_v1.type,
+                                           codeview_jump_to_type(ctp, type->modifier_v1.type), details);
         break;
     case LF_MODIFIER_V2:
         /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */
@@ -751,151 +832,189 @@ static struct symt* codeview_parse_one_t
              type->modifier_v2.attribute & 0x02 ? "volatile " : "",
              type->modifier_v2.attribute & 0x04 ? "unaligned " : "",
              type->modifier_v2.attribute & ~0x07 ? "unknown " : "");
-        symt = codeview_get_type(type->modifier_v2.type, FALSE);
+        if (!(symt = codeview_get_type(type->modifier_v2.type, TRUE)))
+            symt = codeview_parse_one_type(ctp, type->modifier_v2.type,
+                                           codeview_jump_to_type(ctp, type->modifier_v2.type), details);
         break;
 
     case LF_POINTER_V1:
-        symt = codeview_add_type_pointer(ctp->module,
-                                         type->pointer_v1.datatype);
+        symt = codeview_add_type_pointer(ctp, existing, type->pointer_v1.datatype);
         break;
     case LF_POINTER_V2:
-        symt = codeview_add_type_pointer(ctp->module,
-                                         type->pointer_v2.datatype);
+        symt = codeview_add_type_pointer(ctp, existing, type->pointer_v2.datatype);
         break;
 
     case LF_ARRAY_V1:
-        leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
-        p_name = (const struct p_string*)((const unsigned char*)&type->array_v1.arrlen + leaf_len);
-
-        symt = codeview_add_type_array(ctp->module, terminate_string(p_name),
-                                       type->array_v1.elemtype, type->array_v1.idxtype, value);
+        if (existing) symt = codeview_cast_symt(existing, SymTagArrayType);
+        else
+        {
+            leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
+            p_name = (const struct p_string*)((const unsigned char*)&type->array_v1.arrlen + leaf_len);
+            symt = codeview_add_type_array(ctp, terminate_string(p_name),
+                                           type->array_v1.elemtype,
+                                           type->array_v1.idxtype, value);
+        }
         break;
     case LF_ARRAY_V2:
-        leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
-        p_name = (const struct p_string*)((const unsigned char*)&type->array_v2.arrlen + leaf_len);
+        if (existing) symt = codeview_cast_symt(existing, SymTagArrayType);
+        else
+        {
+            leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
+            p_name = (const struct p_string*)((const unsigned char*)&type->array_v2.arrlen + leaf_len);
 
-        symt = codeview_add_type_array(ctp->module, terminate_string(p_name),
-                                       type->array_v2.elemtype, type->array_v2.idxtype, value);
+            symt = codeview_add_type_array(ctp, terminate_string(p_name),
+                                           type->array_v2.elemtype,
+                                           type->array_v2.idxtype, value);
+        }
         break;
     case LF_ARRAY_V3:
-        leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
-        c_name = (const char*)&type->array_v3.arrlen + leaf_len;
+        if (existing) symt = codeview_cast_symt(existing, SymTagArrayType);
+        else
+        {
+            leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
+            c_name = (const char*)&type->array_v3.arrlen + leaf_len;
 
-        symt = codeview_add_type_array(ctp->module, c_name,
-                                       type->array_v3.elemtype, type->array_v3.idxtype, value);
+            symt = codeview_add_type_array(ctp, c_name,
+                                           type->array_v3.elemtype,
+                                           type->array_v3.idxtype, value);
+        }
         break;
 
     case LF_STRUCTURE_V1:
     case LF_CLASS_V1:
         leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
         p_name = (const struct p_string*)((const unsigned char*)&type->struct_v1.structlen + leaf_len);
-        type_ref = codeview_jump_to_type(ctp, type->struct_v1.fieldlist);
-        symt = codeview_add_type_struct(ctp, terminate_string(p_name),
-                                        value, type_ref,
+        symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name), value,
                                         type->generic.id == LF_CLASS_V1 ? UdtClass : UdtStruct);
+        if (details)
+        {
+            codeview_add_type(curr_type, symt);
+            codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt, 
+                                                type->struct_v1.fieldlist);
+        }
         break;
 
     case LF_STRUCTURE_V2:
     case LF_CLASS_V2:
         leaf_len = numeric_leaf(&value, &type->struct_v2.structlen);
         p_name = (const struct p_string*)((const unsigned char*)&type->struct_v2.structlen + leaf_len);
-        type_ref = codeview_jump_to_type(ctp, type->struct_v2.fieldlist);
-        symt = codeview_add_type_struct(ctp, terminate_string(p_name),
-                                        value, type_ref,
+        symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name), value,
                                         type->generic.id == LF_CLASS_V2 ? UdtClass : UdtStruct);
+        if (details)
+        {
+            codeview_add_type(curr_type, symt);
+            codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
+                                                type->struct_v2.fieldlist);
+        }
         break;
 
     case LF_STRUCTURE_V3:
     case LF_CLASS_V3:
         leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
         c_name = (const char*)&type->struct_v3.structlen + leaf_len;
-        type_ref = codeview_jump_to_type(ctp, type->struct_v3.fieldlist);
-        symt = codeview_add_type_struct(ctp, c_name,
-                                        value, type_ref,
+        symt = codeview_add_type_struct(ctp, existing, c_name, value,
                                         type->generic.id == LF_CLASS_V3 ? UdtClass : UdtStruct);
+        if (details)
+        {
+            codeview_add_type(curr_type, symt);
+            codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
+                                                type->struct_v3.fieldlist);
+        }
         break;
 
     case LF_UNION_V1:
         leaf_len = numeric_leaf(&value, &type->union_v1.un_len);
         p_name = (const struct p_string*)((const unsigned char*)&type->union_v1.un_len + leaf_len);
-        type_ref = codeview_jump_to_type(ctp, type->union_v1.fieldlist);
-        symt = codeview_add_type_struct(ctp, terminate_string(p_name),
-                                        value, type_ref, UdtUnion);
+        symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name),
+                                        value, UdtUnion);
+        if (details)
+        {
+            codeview_add_type(curr_type, symt);
+            codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
+                                                type->union_v1.fieldlist);
+        }
         break;
 
     case LF_UNION_V2:
         leaf_len = numeric_leaf(&value, &type->union_v2.un_len);
         p_name = (const struct p_string*)((const unsigned char*)&type->union_v2.un_len + leaf_len);
-        type_ref = codeview_jump_to_type(ctp, type->union_v2.fieldlist);
-        symt = codeview_add_type_struct(ctp, terminate_string(p_name),
-                                        value, type_ref, UdtUnion);
+        symt = codeview_add_type_struct(ctp, existing, terminate_string(p_name),
+                                        value, UdtUnion);
+        if (details)
+        {
+            codeview_add_type(curr_type, symt);
+            codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
+                                                type->union_v2.fieldlist);
+        }
         break;
+
     case LF_UNION_V3:
         leaf_len = numeric_leaf(&value, &type->union_v3.un_len);
         c_name = (const char*)&type->union_v3.un_len + leaf_len;
-        type_ref = codeview_jump_to_type(ctp, type->union_v3.fieldlist);
-        symt = codeview_add_type_struct(ctp, c_name,
-                                        value, type_ref, UdtUnion);
+        symt = codeview_add_type_struct(ctp, existing, c_name,
+                                        value, UdtUnion);
+        if (details)
+        {
+            codeview_add_type(curr_type, symt);
+            codeview_add_type_struct_field_list(ctp, (struct symt_udt*)symt,
+                                                type->union_v3.fieldlist);
+        }
         break;
 
     case LF_ENUM_V1:
-        type_ref = codeview_jump_to_type(ctp, type->enumeration_v1.fieldlist);
-        symt = codeview_add_type_enum(ctp->module, 
+        symt = codeview_add_type_enum(ctp, existing,
                                       terminate_string(&type->enumeration_v1.p_name),
-                                      type_ref);
+                                      type->enumeration_v1.fieldlist);
         break;
 
     case LF_ENUM_V2:
-        type_ref = codeview_jump_to_type(ctp, type->enumeration_v2.fieldlist);
-        symt = codeview_add_type_enum(ctp->module,
+        symt = codeview_add_type_enum(ctp, existing,
                                       terminate_string(&type->enumeration_v2.p_name),
-                                      type_ref);
+                                      type->enumeration_v2.fieldlist);
         break;
 
     case LF_ENUM_V3:
-        type_ref = codeview_jump_to_type(ctp, type->enumeration_v3.fieldlist);
-        symt = codeview_add_type_enum(ctp->module, type->enumeration_v3.name,
-                                      type_ref);
+        symt = codeview_add_type_enum(ctp, existing, type->enumeration_v3.name,
+                                      type->enumeration_v3.fieldlist);
         break;
 
     case LF_PROCEDURE_V1:
-        symt = codeview_add_func_signature(ctp, 
+        symt = codeview_new_func_signature(ctp, existing,
                                            type->procedure_v1.rvtype,
-                                           type->procedure_v1.arglist,
+                                           details ? type->procedure_v1.arglist : 0,
                                            type->procedure_v1.call);
         break;
     case LF_PROCEDURE_V2:
-        symt = codeview_add_func_signature(ctp, 
+        symt = codeview_new_func_signature(ctp, existing,
                                            type->procedure_v2.rvtype,
-                                           type->procedure_v2.arglist,
+                                           details ? type->procedure_v2.arglist : 0,
                                            type->procedure_v2.call);
         break;
     case LF_MFUNCTION_V1:
         /* FIXME: for C++, this is plain wrong, but as we don't use arg types
          * nor class information, this would just do for now
          */
-        symt = codeview_add_func_signature(ctp,
+        symt = codeview_new_func_signature(ctp, existing,
                                            type->mfunction_v1.rvtype,
-                                           type->mfunction_v1.arglist,
+                                           details ? type->mfunction_v1.arglist : 0,
                                            type->mfunction_v1.call);
         break;
     case LF_MFUNCTION_V2:
         /* FIXME: for C++, this is plain wrong, but as we don't use arg types
          * nor class information, this would just do for now
          */
-        symt = codeview_add_func_signature(ctp,
+        symt = codeview_new_func_signature(ctp, existing,
                                            type->mfunction_v2.rvtype,
-                                           type->mfunction_v2.arglist,
+                                           details ? type->mfunction_v2.arglist : 0,
                                            type->mfunction_v2.call);
         break;
 
     default:
         FIXME("Unsupported type-id leaf %x\n", type->generic.id);
         dump(type, 2 + type->generic.len);
-        symt = NULL;
-        break;
+        return FALSE;
     }
-    return (symt && codeview_add_type(curr_type, symt)) ? symt : NULL;
+    return codeview_add_type(curr_type, symt) ? symt : NULL;
 }
 
 static int codeview_parse_type_table(struct codeview_type_parse* ctp)
@@ -919,7 +1038,7 @@ static int codeview_parse_type_table(str
          *      8000-8010       for numeric leafes
          */
         if (type->generic.id & 0x8600) continue;
-        codeview_parse_one_type(ctp, curr_type, type);
+        codeview_parse_one_type(ctp, curr_type, type, TRUE);
     }
 
     return TRUE;





More information about the wine-patches mailing list