[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