[PATCH 06/13] [DbgHelp]: fieldlist
Eric Pouech
eric.pouech at wanadoo.fr
Sat Mar 18 06:32:50 CST 2006
- now that we have offset tables to type, we can cleanly
parse the field-lists and remove the associated kludges
- also adding internal structure for easing parameter sharing
across functions (codeview_type_parse)
- in mscvpdb.h, also reparated the type records that are
referenced from other type records (union codeview_type_ref)
from type records referenced by symbols (union codeview_type)
A+
---
dlls/dbghelp/msc.c | 210 +++++++++++++++++++++++-------------------------
dlls/dbghelp/mscvpdb.h | 30 +++++--
2 files changed, 121 insertions(+), 119 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index 8e269c7..c7ae392 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 1996, Eric Youngdale.
* Copyright (C) 1999-2000, Ulrich Weigand.
- * Copyright (C) 2004-2005, Eric Pouech.
+ * Copyright (C) 2004-2006, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -328,6 +328,21 @@ static struct symt* codeview_get_type(u
return symt;
}
+struct codeview_type_parse
+{
+ struct module* module;
+ const BYTE* table;
+ const DWORD* offset;
+ DWORD num;
+};
+
+static inline const void* codeview_jump_to_type(struct codeview_type_parse* ctp, DWORD idx)
+{
+ if (idx < FIRST_DEFINABLE_TYPE) return NULL;
+ idx -= FIRST_DEFINABLE_TYPE;
+ return (idx >= ctp->num) ? NULL : (ctp->table + ctp->offset[idx]);
+}
+
static int codeview_add_type(unsigned int typeno, struct symt* dt)
{
if (typeno < FIRST_DEFINABLE_TYPE)
@@ -437,24 +452,24 @@ static int codeview_add_type_bitfield(un
return codeview_add_type(typeno, &cv_current_module->bitfields[cv_current_module->used_bitfields++].symt);
}
-static int codeview_add_type_enum_field_list(struct module* module,
- unsigned int typeno,
- const unsigned char* list, int len)
-{
- struct symt_enum* symt;
- const unsigned char* ptr = list;
+static int codeview_add_type_enum_field_list(struct module* module,
+ struct symt_enum* symt,
+ const union codeview_reftype* ref_type)
+{
+ const unsigned char* ptr = ref_type->fieldlist.list;
+ const unsigned char* last = (const BYTE*)ref_type + ref_type->generic.len + 2;
+ const union codeview_fieldtype* type;
- symt = symt_new_enum(module, NULL);
- while (ptr - list < len)
+ while (ptr < last)
{
- const union codeview_fieldtype* type = (const union codeview_fieldtype*)ptr;
-
if (*ptr >= 0xf0) /* LF_PAD... */
{
ptr += *ptr & 0x0f;
continue;
}
+ type = (const union codeview_fieldtype*)ptr;
+
switch (type->generic.id)
{
case LF_ENUMERATE_V1:
@@ -481,32 +496,31 @@ static int codeview_add_type_enum_field_
return FALSE;
}
}
-
- return codeview_add_type(typeno, &symt->symt);
+ return TRUE;
}
-static int codeview_add_type_struct_field_list(struct module* module,
- unsigned int typeno,
- const unsigned char* list, int len)
+static int codeview_add_type_struct_field_list(struct module* module,
+ struct symt_udt* symt,
+ const union codeview_reftype* ref_type)
{
- struct symt_udt* symt;
- const unsigned char* ptr = list;
+ const unsigned char* ptr = ref_type->fieldlist.list;
+ const unsigned char* last = (const BYTE*)ref_type + ref_type->generic.len + 2;
int value, leaf_len;
const struct p_string* p_name;
const char* c_name;
struct symt* subtype;
+ const union codeview_fieldtype* type;
- symt = symt_new_udt(module, NULL, 0, UdtStruct /* don't care */);
- while (ptr - list < len)
+ while (ptr < last)
{
- const union codeview_fieldtype* type = (const union codeview_fieldtype*)ptr;
-
if (*ptr >= 0xf0) /* LF_PAD... */
{
- ptr +=* ptr & 0x0f;
+ ptr += *ptr & 0x0f;
continue;
}
+ type = (const union codeview_fieldtype*)ptr;
+
switch (type->generic.id)
{
case LF_BCLASS_V1:
@@ -699,31 +713,26 @@ static int codeview_add_type_struct_fiel
}
}
- return codeview_add_type(typeno, &symt->symt);
+ return TRUE;
}
static int codeview_add_type_enum(struct module* module, unsigned int typeno,
- const char* name, unsigned int fieldlist)
+ const char* name, const union codeview_reftype* fieldlist)
{
struct symt_enum* symt = symt_new_enum(module, name);
- struct symt* list = codeview_get_type(fieldlist, FALSE);
-
- /* FIXME: this is rather ugly !!! */
- if (list) symt->vchildren = ((struct symt_enum*)list)->vchildren;
+ if (fieldlist) codeview_add_type_enum_field_list(module, symt, fieldlist);
return codeview_add_type(typeno, &symt->symt);
}
static int codeview_add_type_struct(struct module* module, unsigned int typeno,
const char* name, int structlen,
- unsigned int fieldlist, enum UdtKind kind)
+ const union codeview_reftype* fieldlist,
+ enum UdtKind kind)
{
struct symt_udt* symt = symt_new_udt(module, name, structlen, kind);
- struct symt* list = codeview_get_type(fieldlist, FALSE);
-
- /* FIXME: this is rather ugly !!! */
- if (list) symt->vchildren = ((struct symt_udt*)list)->vchildren;
+ if (fieldlist) codeview_add_type_struct_field_list(module, symt, fieldlist);
return codeview_add_type(typeno, &symt->symt);
}
@@ -737,20 +746,20 @@ static int codeview_new_func_signature(s
return codeview_add_type(typeno, symt);
}
-static int codeview_parse_type_table(struct module* module, const BYTE* table,
- const DWORD* offset, DWORD num)
+static int codeview_parse_type_table(struct codeview_type_parse* ctp)
{
- unsigned int curr_type = 0x1000;
+ unsigned int curr_type = FIRST_DEFINABLE_TYPE;
int retv = TRUE;
const union codeview_type* type;
+ const union codeview_reftype*type_ref;
int value, leaf_len;
const struct p_string* p_name;
const char* c_name;
- for (curr_type = 0x1000; retv && curr_type < 0x1000 + num; curr_type++)
+ for (curr_type = FIRST_DEFINABLE_TYPE; retv && curr_type < FIRST_DEFINABLE_TYPE + ctp->num; curr_type++)
{
retv = TRUE;
- type = (const union codeview_type*)(table + offset[curr_type - 0x1000]);
+ type = codeview_jump_to_type(ctp, curr_type);
/* type records we're interested in are the ones referenced by symbols
* The known ranges are (X mark the ones we want):
@@ -765,9 +774,7 @@ static int codeview_parse_type_table(str
*/
if ((type->generic.id & 0x8600) &&
type->generic.id != LF_BITFIELD_V1 && /* still some cases to fix */
- type->generic.id != LF_BITFIELD_V2 &&
- type->generic.id != LF_FIELDLIST_V1 &&
- type->generic.id != LF_FIELDLIST_V2)
+ type->generic.id != LF_BITFIELD_V2)
continue;
switch (type->generic.id)
{
@@ -797,11 +804,11 @@ static int codeview_parse_type_table(str
break;
case LF_POINTER_V1:
- retv = codeview_add_type_pointer(module, curr_type,
+ retv = codeview_add_type_pointer(ctp->module, curr_type,
type->pointer_v1.datatype);
break;
case LF_POINTER_V2:
- retv = codeview_add_type_pointer(module, curr_type,
+ retv = codeview_add_type_pointer(ctp->module, curr_type,
type->pointer_v2.datatype);
break;
@@ -809,21 +816,21 @@ static int codeview_parse_type_table(str
leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
p_name = (const struct p_string*)((const unsigned char*)&type->array_v1.arrlen + leaf_len);
- retv = codeview_add_type_array(module, curr_type, terminate_string(p_name),
+ retv = codeview_add_type_array(ctp->module, curr_type, 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);
- retv = codeview_add_type_array(module, curr_type, terminate_string(p_name),
+ retv = codeview_add_type_array(ctp->module, curr_type, 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;
- retv = codeview_add_type_array(module, curr_type, c_name,
+ retv = codeview_add_type_array(ctp->module, curr_type, c_name,
type->array_v3.elemtype, type->array_v3.idxtype, value);
break;
@@ -842,40 +849,14 @@ static int codeview_parse_type_table(str
type->bitfield_v2.nbits,
type->bitfield_v2.type);
break;
- case LF_FIELDLIST_V1:
- case LF_FIELDLIST_V2:
- {
- /*
- * A 'field list' is a CodeView-specific data type which doesn't
- * directly correspond to any high-level data type. It is used
- * to hold the collection of members of a struct, class, union
- * or enum type. The actual definition of that type will follow
- * later, and refer to the field list definition record.
- *
- * As we don't have a field list type ourselves, we look ahead
- * in the field list to try to find out whether this field list
- * will be used for an enum or struct type, and create a dummy
- * type of the corresponding sort. Later on, the definition of
- * the 'real' type will copy the member / enumeration data.
- */
- const unsigned char* list = type->fieldlist.list;
- int len = ((const BYTE*)type + type->generic.len + 2) - list;
-
- if (((const union codeview_fieldtype*)list)->generic.id == LF_ENUMERATE_V1 ||
- ((const union codeview_fieldtype*)list)->generic.id == LF_ENUMERATE_V3)
- retv = codeview_add_type_enum_field_list(module, curr_type, list, len);
- else
- retv = codeview_add_type_struct_field_list(module, curr_type, list, len);
- }
- 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);
-
- retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
- value, type->struct_v1.fieldlist,
+ type_ref = codeview_jump_to_type(ctp, type->struct_v1.fieldlist);
+ retv = codeview_add_type_struct(ctp->module, curr_type, terminate_string(p_name),
+ value, type_ref,
type->generic.id == LF_CLASS_V1 ? UdtClass : UdtStruct);
break;
@@ -883,9 +864,9 @@ static int codeview_parse_type_table(str
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);
-
- retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
- value, type->struct_v2.fieldlist,
+ type_ref = codeview_jump_to_type(ctp, type->struct_v2.fieldlist);
+ retv = codeview_add_type_struct(ctp->module, curr_type, terminate_string(p_name),
+ value, type_ref,
type->generic.id == LF_CLASS_V2 ? UdtClass : UdtStruct);
break;
@@ -893,53 +874,62 @@ static int codeview_parse_type_table(str
case LF_CLASS_V3:
leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
c_name = (const char*)&type->struct_v3.structlen + leaf_len;
-
- retv = codeview_add_type_struct(module, curr_type, c_name,
- value, type->struct_v3.fieldlist,
+ type_ref = codeview_jump_to_type(ctp, type->struct_v3.fieldlist);
+ retv = codeview_add_type_struct(ctp->module, curr_type, c_name,
+ value, type_ref,
type->generic.id == LF_CLASS_V3 ? UdtClass : UdtStruct);
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);
-
- retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
- value, type->union_v1.fieldlist, UdtUnion);
+ type_ref = codeview_jump_to_type(ctp, type->union_v1.fieldlist);
+ retv = codeview_add_type_struct(ctp->module, curr_type, terminate_string(p_name),
+ value, type_ref, UdtUnion);
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);
-
- retv = codeview_add_type_struct(module, curr_type, terminate_string(p_name),
- value, type->union_v2.fieldlist, UdtUnion);
+ type_ref = codeview_jump_to_type(ctp, type->union_v2.fieldlist);
+ retv = codeview_add_type_struct(ctp->module, curr_type, terminate_string(p_name),
+ value, type_ref, UdtUnion);
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;
-
- retv = codeview_add_type_struct(module, curr_type, c_name,
- value, type->union_v3.fieldlist, UdtUnion);
+ type_ref = codeview_jump_to_type(ctp, type->union_v3.fieldlist);
+ retv = codeview_add_type_struct(ctp->module, curr_type, c_name,
+ value, type_ref, UdtUnion);
+ break;
case LF_ENUM_V1:
- retv = codeview_add_type_enum(module, curr_type, terminate_string(&type->enumeration_v1.p_name),
- type->enumeration_v1.field);
+ type_ref = codeview_jump_to_type(ctp, type->enumeration_v1.fieldlist);
+ retv = codeview_add_type_enum(ctp->module, curr_type,
+ terminate_string(&type->enumeration_v1.p_name),
+ type_ref);
break;
case LF_ENUM_V2:
- retv = codeview_add_type_enum(module, curr_type, terminate_string(&type->enumeration_v2.p_name),
- type->enumeration_v2.field);
+ type_ref = codeview_jump_to_type(ctp, type->enumeration_v2.fieldlist);
+ retv = codeview_add_type_enum(ctp->module, curr_type,
+ terminate_string(&type->enumeration_v2.p_name),
+ type_ref);
break;
+
case LF_ENUM_V3:
- retv = codeview_add_type_enum(module, curr_type, type->enumeration_v3.name,
- type->enumeration_v3.field);
+ type_ref = codeview_jump_to_type(ctp, type->enumeration_v3.fieldlist);
+ retv = codeview_add_type_enum(ctp->module, curr_type, type->enumeration_v3.name,
+ type_ref);
break;
+
case LF_PROCEDURE_V1:
- retv = codeview_new_func_signature(module, curr_type,
+ retv = codeview_new_func_signature(ctp->module, curr_type,
type->procedure_v1.rvtype,
type->procedure_v1.call);
break;
case LF_PROCEDURE_V2:
- retv = codeview_new_func_signature(module, curr_type,
+ retv = codeview_new_func_signature(ctp->module, curr_type,
type->procedure_v2.rvtype,
type->procedure_v2.call);
break;
@@ -947,7 +937,7 @@ static int codeview_parse_type_table(str
/* FIXME: for C++, this is plain wrong, but as we don't use arg types
* nor class information, this would just do for now
*/
- retv = codeview_new_func_signature(module, curr_type,
+ retv = codeview_new_func_signature(ctp->module, curr_type,
type->mfunction_v1.rvtype,
type->mfunction_v1.call);
break;
@@ -955,7 +945,7 @@ static int codeview_parse_type_table(str
/* FIXME: for C++, this is plain wrong, but as we don't use arg types
* nor class information, this would just do for now
*/
- retv = codeview_new_func_signature(module, curr_type,
+ retv = codeview_new_func_signature(ctp->module, curr_type,
type->mfunction_v2.rvtype,
type->mfunction_v2.call);
break;
@@ -1795,10 +1785,10 @@ static void pdb_process_types(const stru
if (types_image)
{
PDB_TYPES types;
- DWORD* offset;
- DWORD num, total;
- const BYTE* table;
+ struct codeview_type_parse ctp;
+ DWORD total;
const BYTE* ptr;
+ DWORD* offset;
pdb_convert_types_header(&types, types_image);
@@ -1814,21 +1804,23 @@ static void pdb_process_types(const stru
ERR("-Unknown type info version %ld\n", types.version);
}
+ ctp.module = msc_dbg->module;
/* reconstruct the types offset...
* FIXME: maybe it's present in the newest PDB_TYPES structures
*/
total = types.last_index - types.first_index + 1;
offset = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * total);
- table = ptr = types_image + types.type_offset;
- num = 0;
- while (ptr < table + types.type_size && num < total)
+ ctp.table = ptr = types_image + types.type_offset;
+ ctp.num = 0;
+ while (ptr < ctp.table + types.type_size && ctp.num < total)
{
- offset[num++] = ptr - table;
+ offset[ctp.num++] = ptr - ctp.table;
ptr += ((const union codeview_type*)ptr)->generic.len + 2;
}
+ ctp.offset = offset;
/* Read type table */
- codeview_parse_type_table(msc_dbg->module, table, offset, num);
+ codeview_parse_type_table(&ctp);
HeapFree(GetProcessHeap(), 0, offset);
pdb_free(types_image);
}
diff --git a/dlls/dbghelp/mscvpdb.h b/dlls/dbghelp/mscvpdb.h
index fa875f5..a836326 100644
--- a/dlls/dbghelp/mscvpdb.h
+++ b/dlls/dbghelp/mscvpdb.h
@@ -294,7 +294,7 @@ union codeview_type
short int id;
short int count;
short int type;
- short int field;
+ short int fieldlist;
short int property;
struct p_string p_name;
} enumeration_v1;
@@ -306,7 +306,7 @@ union codeview_type
short int count;
short int property;
unsigned int type;
- unsigned int field;
+ unsigned int fieldlist;
struct p_string p_name;
} enumeration_v2;
@@ -317,7 +317,7 @@ union codeview_type
short int count;
short int property;
unsigned int type;
- unsigned int field;
+ unsigned int fieldlist;
char name[1];
} enumeration_v3;
@@ -325,13 +325,6 @@ union codeview_type
{
unsigned short int len;
short int id;
- unsigned char list[1];
- } fieldlist;
-
- struct
- {
- unsigned short int len;
- short int id;
unsigned short int rvtype;
unsigned char call;
unsigned char reserved;
@@ -379,6 +372,23 @@ union codeview_type
} mfunction_v2;
};
+union codeview_reftype
+{
+ struct
+ {
+ unsigned short int len;
+ short int id;
+ } generic;
+
+ struct
+ {
+ unsigned short int len;
+ short int id;
+ unsigned char list[1];
+ } fieldlist;
+
+};
+
union codeview_fieldtype
{
struct
More information about the wine-patches
mailing list