Improved CodeView type information loader.
diff --git a/debugger/msc.c b/debugger/msc.c
index 660181e..45dd2af 100644
--- a/debugger/msc.c
+++ b/debugger/msc.c
@@ -287,9 +287,10 @@
short int id;
short int elemtype;
short int idxtype;
- unsigned char arrlen;
- unsigned char namelen;
+ unsigned short int arrlen; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} array;
struct
@@ -298,9 +299,10 @@
short int id;
unsigned int elemtype;
unsigned int idxtype;
- unsigned char arrlen;
- unsigned char namelen;
+ unsigned short int arrlen; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} array32;
struct
@@ -312,9 +314,10 @@
short int property;
short int derived;
short int vshape;
- unsigned short structlen;
- unsigned char namelen;
+ unsigned short int structlen; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} structure;
struct
@@ -326,9 +329,10 @@
unsigned int fieldlist;
unsigned int derived;
unsigned int vshape;
- unsigned short structlen;
- unsigned char namelen;
+ unsigned short int structlen; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} structure32;
struct
@@ -336,11 +340,12 @@
short int len;
short int id;
short int count;
- short int field;
+ short int fieldlist;
short int property;
- unsigned short un_len;
- unsigned char namelen;
+ unsigned short int un_len; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} t_union;
struct
@@ -349,10 +354,11 @@
short int id;
short int count;
short int property;
- unsigned int field;
- unsigned short un_len;
- unsigned char namelen;
+ unsigned int fieldlist;
+ unsigned short int un_len; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} t_union32;
struct
@@ -363,7 +369,6 @@
short int type;
short int field;
short int property;
- unsigned char namelen;
unsigned char name[1];
} enumeration;
@@ -375,27 +380,98 @@
short int property;
unsigned int type;
unsigned int field;
- unsigned char namelen;
unsigned char name[1];
} enumeration32;
struct
{
+ short int len;
short int id;
- short int attribute;
- unsigned short int value;
- unsigned char namelen;
- unsigned char name[1];
- } enumerate;
+ unsigned char list[1];
+ } fieldlist;
+};
+
+union codeview_fieldtype
+{
+ struct
+ {
+ short int id;
+ } generic;
struct
{
short int id;
short int type;
short int attribute;
- unsigned short int offset;
- unsigned char namelen;
+ unsigned short int offset; /* numeric leaf */
+ } bclass;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int type;
+ unsigned short int offset; /* numeric leaf */
+ } bclass32;
+
+ struct
+ {
+ short int id;
+ short int btype;
+ short int vbtype;
+ short int attribute;
+ unsigned short int vbpoff; /* numeric leaf */
+#if 0
+ unsigned short int vboff; /* numeric leaf */
+#endif
+ } vbclass;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int btype;
+ unsigned int vbtype;
+ unsigned short int vbpoff; /* numeric leaf */
+#if 0
+ unsigned short int vboff; /* numeric leaf */
+#endif
+ } vbclass32;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned short int value; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
+ } enumerate;
+
+ struct
+ {
+ short int id;
+ short int type;
+ unsigned char name[1];
+ } friendfcn;
+
+ struct
+ {
+ short int id;
+ short int _pad0;
+ unsigned int type;
+ unsigned char name[1];
+ } friendfcn32;
+
+ struct
+ {
+ short int id;
+ short int type;
+ short int attribute;
+ unsigned short int offset; /* numeric leaf */
+#if 0
+ unsigned char name[1];
+#endif
} member;
struct
@@ -403,10 +479,156 @@
short int id;
short int attribute;
unsigned int type;
- unsigned short int offset;
- unsigned char namelen;
+ unsigned short int offset; /* numeric leaf */
+#if 0
unsigned char name[1];
+#endif
} member32;
+
+ struct
+ {
+ short int id;
+ short int type;
+ short int attribute;
+ unsigned char name[1];
+ } stmember;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int type;
+ unsigned char name[1];
+ } stmember32;
+
+ struct
+ {
+ short int id;
+ short int count;
+ short int mlist;
+ unsigned char name[1];
+ } method;
+
+ struct
+ {
+ short int id;
+ short int count;
+ unsigned int mlist;
+ unsigned char name[1];
+ } method32;
+
+ struct
+ {
+ short int id;
+ short int index;
+ unsigned char name[1];
+ } nesttype;
+
+ struct
+ {
+ short int id;
+ short int _pad0;
+ unsigned int index;
+ unsigned char name[1];
+ } nesttype32;
+
+ struct
+ {
+ short int id;
+ short int type;
+ } vfunctab;
+
+ struct
+ {
+ short int id;
+ short int _pad0;
+ unsigned int type;
+ } vfunctab32;
+
+ struct
+ {
+ short int id;
+ short int type;
+ } friendcls;
+
+ struct
+ {
+ short int id;
+ short int _pad0;
+ unsigned int type;
+ } friendcls32;
+
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ short int type;
+ unsigned char name[1];
+ } onemethod;
+ struct
+ {
+ short int id;
+ short int attribute;
+ short int type;
+ unsigned int vtab_offset;
+ unsigned char name[1];
+ } onemethod_virt;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int type;
+ unsigned char name[1];
+ } onemethod32;
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int type;
+ unsigned int vtab_offset;
+ unsigned char name[1];
+ } onemethod32_virt;
+
+ struct
+ {
+ short int id;
+ short int type;
+ unsigned int offset;
+ } vfuncoff;
+
+ struct
+ {
+ short int id;
+ short int _pad0;
+ unsigned int type;
+ unsigned int offset;
+ } vfuncoff32;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ short int index;
+ unsigned char name[1];
+ } nesttypeex;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int index;
+ unsigned char name[1];
+ } nesttypeex32;
+
+ struct
+ {
+ short int id;
+ short int attribute;
+ unsigned int type;
+ unsigned char name[1];
+ } membermodify;
};
#define S_COMPILE 0x0001
@@ -601,6 +823,24 @@
#define LF_VFUNCOFF_32 0x140c
#define LF_NESTTYPEEX_32 0x140d
+#define LF_NUMERIC 0x8000 /* numeric leaf types */
+#define LF_CHAR 0x8000
+#define LF_SHORT 0x8001
+#define LF_USHORT 0x8002
+#define LF_LONG 0x8003
+#define LF_ULONG 0x8004
+#define LF_REAL32 0x8005
+#define LF_REAL64 0x8006
+#define LF_REAL80 0x8007
+#define LF_REAL128 0x8008
+#define LF_QUADWORD 0x8009
+#define LF_UQUADWORD 0x800a
+#define LF_REAL48 0x800b
+#define LF_COMPLEX32 0x800c
+#define LF_COMPLEX64 0x800d
+#define LF_COMPLEX80 0x800e
+#define LF_COMPLEX128 0x800f
+#define LF_VARSTRING 0x8010
@@ -719,524 +959,603 @@
};
+
+/*
+ * CodeView type information parsing
+ */
+
+static int
+numeric_leaf( int *value, unsigned short int *leaf )
+{
+ unsigned short int type = *leaf++;
+ int length = 2;
+
+ if ( type < LF_NUMERIC )
+ {
+ *value = type;
+ }
+ else
+ {
+ switch ( type )
+ {
+ case LF_CHAR:
+ length += 1;
+ *value = *(char *)leaf;
+ break;
+
+ case LF_SHORT:
+ length += 2;
+ *value = *(short *)leaf;
+ break;
+
+ case LF_USHORT:
+ length += 2;
+ *value = *(unsigned short *)leaf;
+ break;
+
+ case LF_LONG:
+ length += 4;
+ *value = *(int *)leaf;
+ break;
+
+ case LF_ULONG:
+ length += 4;
+ *value = *(unsigned int *)leaf;
+ break;
+
+ case LF_QUADWORD:
+ case LF_UQUADWORD:
+ length += 8;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_REAL32:
+ length += 4;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_REAL48:
+ length += 6;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_REAL64:
+ length += 8;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_REAL80:
+ length += 10;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_REAL128:
+ length += 16;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_COMPLEX32:
+ length += 4;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_COMPLEX64:
+ length += 8;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_COMPLEX80:
+ length += 10;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_COMPLEX128:
+ length += 16;
+ *value = 0; /* FIXME */
+ break;
+
+ case LF_VARSTRING:
+ length += 2 + *leaf;
+ *value = 0; /* FIXME */
+ break;
+
+ default:
+ DEBUG_Printf( DBG_CHN_MESG, "Unknown numeric leaf type %04x\n", type );
+ *value = 0;
+ break;
+ }
+ }
+
+ return length;
+}
+
+static char *
+terminate_string( unsigned char *name )
+{
+ static char symname[256];
+
+ int namelen = name[0];
+ assert( namelen >= 0 && namelen < 256 );
+
+ memcpy( symname, name+1, namelen );
+ symname[namelen] = '\0';
+
+ if ( !*symname || strcmp( symname, "__unnamed" ) == 0 )
+ return NULL;
+ else
+ return symname;
+}
+
static
struct datatype * DEBUG_GetCVType(unsigned int typeno)
{
- struct datatype * dt = NULL;
+ struct datatype * dt = NULL;
- /*
- * Convert Codeview type numbers into something we can grok internally.
- * Numbers < 0x1000 are all fixed builtin types. Numbers from 0x1000 and
- * up are all user defined (structs, etc).
- */
- if( typeno < 0x1000 )
+ /*
+ * Convert Codeview type numbers into something we can grok internally.
+ * Numbers < 0x1000 are all fixed builtin types. Numbers from 0x1000 and
+ * up are all user defined (structs, etc).
+ */
+ if ( typeno < 0x1000 )
{
- if( typeno < MAX_BUILTIN_TYPES )
- {
- dt = cv_basic_types[typeno];
- }
+ if ( typeno < MAX_BUILTIN_TYPES )
+ dt = cv_basic_types[typeno];
}
- else
+ else
{
- if( typeno - 0x1000 < num_cv_defined_types )
- {
- dt = cv_defined_types[typeno - 0x1000];
- }
+ if ( typeno - 0x1000 < num_cv_defined_types )
+ dt = cv_defined_types[typeno - 0x1000];
}
- return dt;
+ return dt;
}
static int
-DEBUG_ParseTypeTable(char * table, int len)
+DEBUG_AddCVType( unsigned int typeno, struct datatype *dt )
{
- int arr_max;
- int curr_type;
- enum debug_type fieldtype;
- int elem_size;
- union any_size ptr;
- union any_size ptr2;
- struct datatype * subtype;
- char symname[256];
- union codeview_type * type;
- union codeview_type * type2;
- struct datatype * typeptr;
-
- curr_type = 0x1000;
-
- ptr.c = table;
- while( ptr.c - table < len )
+ while ( typeno - 0x1000 >= num_cv_defined_types )
{
- type = (union codeview_type *) ptr.c;
+ num_cv_defined_types += 0x100;
+ cv_defined_types = (struct datatype **)
+ DBG_realloc( cv_defined_types,
+ num_cv_defined_types * sizeof(struct datatype *) );
- if( curr_type - 0x1000 >= num_cv_defined_types )
- {
- num_cv_defined_types += 0x100;
- cv_defined_types = (struct datatype **) DBG_realloc(cv_defined_types,
- num_cv_defined_types * sizeof(struct datatype *));
- memset(cv_defined_types + num_cv_defined_types - 0x100,
- 0,
- 0x100 * sizeof(struct datatype *));
- if( cv_defined_types == NULL )
- {
- return FALSE;
- }
- }
+ memset( cv_defined_types + num_cv_defined_types - 0x100,
+ 0,
+ 0x100 * sizeof(struct datatype *) );
- switch(type->generic.id)
- {
- case LF_POINTER:
- cv_defined_types[curr_type - 0x1000] =
- DEBUG_FindOrMakePointerType(DEBUG_GetCVType(type->pointer.datatype));
- break;
- case LF_POINTER_32:
- cv_defined_types[curr_type - 0x1000] =
- DEBUG_FindOrMakePointerType(DEBUG_GetCVType(type->pointer32.datatype));
- break;
- case LF_ARRAY:
- if( type->array.arrlen >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- break;
- }
- if( type->array.namelen != 0 )
- {
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->array.name, type->array.namelen);
- typeptr = DEBUG_NewDataType(DT_ARRAY, symname);
- }
- else
- {
- typeptr = DEBUG_NewDataType(DT_ARRAY, NULL);
- }
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- subtype = DEBUG_GetCVType(type->array.elemtype);
- if( (subtype == NULL)
- || (elem_size = DEBUG_GetObjectSize(subtype)) == 0 )
- {
- arr_max = 0;
- }
- else
- {
- arr_max = type->array.arrlen / DEBUG_GetObjectSize(subtype);
- }
-
- DEBUG_SetArrayParams(typeptr, 0, arr_max, subtype);
- break;
- case LF_ARRAY_32:
- if( type->array32.arrlen >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- break;
- }
- if( type->array32.namelen != 0 )
- {
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->array32.name, type->array32.namelen);
- typeptr = DEBUG_NewDataType(DT_ARRAY, symname);
- }
- else
- {
- typeptr = DEBUG_NewDataType(DT_ARRAY, NULL);
- }
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- subtype = DEBUG_GetCVType(type->array32.elemtype);
- if( (subtype == NULL)
- || (elem_size = DEBUG_GetObjectSize(subtype)) == 0 )
- {
- arr_max = 0;
- }
- else
- {
- arr_max = type->array32.arrlen / DEBUG_GetObjectSize(subtype);
- }
-
- DEBUG_SetArrayParams(typeptr, 0, arr_max, subtype);
- break;
- case LF_FIELDLIST:
- /*
- * This is where the basic list of fields is defined for
- * structures and classes.
- *
- * First, we need to look ahead and see whether we are building
- * a fieldlist for an enum or a struct.
- */
- ptr2.i = ptr.i + 1;
- type2 = (union codeview_type *) ptr2.c;
- if( type2->member.id == LF_MEMBER )
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
- fieldtype = DT_STRUCT;
- }
- else if( type2->member.id == LF_ENUMERATE )
- {
- typeptr = DEBUG_NewDataType(DT_ENUM, NULL);
- fieldtype = DT_ENUM;
- }
- else
- {
- break;
- }
-
- cv_defined_types[curr_type - 0x1000] = typeptr;
- while( ptr2.c < (ptr.c + ((type->generic.len + 3) & ~3)) )
- {
- type2 = (union codeview_type *) ptr2.c;
- if( type2->member.id == LF_MEMBER && fieldtype == DT_STRUCT )
- {
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type2->member.name, type2->member.namelen);
-
- subtype = DEBUG_GetCVType(type2->member.type);
- elem_size = 0;
- if( subtype != NULL )
- {
- elem_size = DEBUG_GetObjectSize(subtype);
- }
-
- if( type2->member.offset >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- }
- else
- {
- DEBUG_AddStructElement(typeptr, symname, subtype,
- type2->member.offset << 3,
- elem_size << 3);
- }
- }
- else if( type2->member.id == LF_ENUMERATE && fieldtype == DT_ENUM )
- {
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type2->enumerate.name, type2->enumerate.namelen);
-
- if( type2->enumerate.value >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- }
- else
- {
- DEBUG_AddStructElement(typeptr, symname, NULL,
- type2->enumerate.value, 0);
- }
- }
- else
- {
- /*
- * Something else I have never seen before. Either wrong type of
- * object in the fieldlist, or some other problem which I wouldn't
- * really know how to handle until it came up.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Unexpected entry in fieldlist\n");
- break;
- }
-
-
- ptr2.c += ((type2->member.namelen + 9 + 3) & ~3);
- }
- break;
- case LF_FIELDLIST_32:
- /*
- * This is where the basic list of fields is defined for
- * structures and classes.
- *
- * First, we need to look ahead and see whether we are building
- * a fieldlist for an enum or a struct.
- */
- ptr2.i = ptr.i + 1;
- type2 = (union codeview_type *) ptr2.c;
- if( type2->member32.id == LF_MEMBER_32 )
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
- fieldtype = DT_STRUCT;
- }
- else if( type2->member32.id == LF_ENUMERATE )
- {
- typeptr = DEBUG_NewDataType(DT_ENUM, NULL);
- fieldtype = DT_ENUM;
- }
- else
- {
- break;
- }
-
- cv_defined_types[curr_type - 0x1000] = typeptr;
- while( ptr2.c < (ptr.c + ((type->generic.len + 3) & ~3)) )
- {
- type2 = (union codeview_type *) ptr2.c;
- if( type2->member.id == LF_MEMBER_32 && fieldtype == DT_STRUCT )
- {
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type2->member32.name, type2->member32.namelen);
-
- subtype = DEBUG_GetCVType(type2->member32.type);
- elem_size = 0;
- if( subtype != NULL )
- {
- elem_size = DEBUG_GetObjectSize(subtype);
- }
-
- if( type2->member32.offset >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- }
- else
- {
- DEBUG_AddStructElement(typeptr, symname, subtype,
- type2->member32.offset << 3,
- elem_size << 3);
- }
- }
- else if( type2->member32.id == LF_ENUMERATE && fieldtype == DT_ENUM )
- {
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type2->enumerate.name, type2->enumerate.namelen);
-
- if( type2->enumerate.value >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- }
- else
- {
- DEBUG_AddStructElement(typeptr, symname, NULL,
- type2->enumerate.value, 0);
- }
- }
- else
- {
- /*
- * Something else I have never seen before. Either wrong type of
- * object in the fieldlist, or some other problem which I wouldn't
- * really know how to handle until it came up.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Unexpected entry in fieldlist\n");
- break;
- }
-
-
- ptr2.c += ((type2->member32.namelen + 9 + 3) & ~3);
- }
- break;
- case LF_STRUCTURE:
- case LF_CLASS:
- if( type->structure.structlen >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- break;
- }
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->structure.name, type->structure.namelen);
- if( strcmp(symname, "__unnamed") == 0 )
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
- }
- else
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, symname);
- }
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- /*
- * Now copy the relevant bits from the fieldlist that we specified.
- */
- subtype = DEBUG_GetCVType(type->structure.fieldlist);
-
- if( subtype != NULL )
- {
- DEBUG_SetStructSize(typeptr, type->structure.structlen);
- DEBUG_CopyFieldlist(typeptr, subtype);
- }
- break;
- case LF_STRUCTURE_32:
- case LF_CLASS_32:
- if( type->structure32.structlen >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- break;
- }
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->structure32.name, type->structure32.namelen);
- if( strcmp(symname, "__unnamed") == 0 )
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
- }
- else
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, symname);
- }
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- /*
- * Now copy the relevant bits from the fieldlist that we specified.
- */
- subtype = DEBUG_GetCVType(type->structure32.fieldlist);
-
- if( subtype != NULL )
- {
- DEBUG_SetStructSize(typeptr, type->structure32.structlen);
- DEBUG_CopyFieldlist(typeptr, subtype);
- }
- break;
- case LF_UNION:
- if( type->t_union.un_len >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- break;
- }
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->t_union.name, type->t_union.namelen);
-
- if( strcmp(symname, "__unnamed") == 0 )
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
- }
- else
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, symname);
- }
-
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- /*
- * Now copy the relevant bits from the fieldlist that we specified.
- */
- subtype = DEBUG_GetCVType(type->t_union.field);
-
- if( subtype != NULL )
- {
- DEBUG_SetStructSize(typeptr, type->t_union.un_len);
- DEBUG_CopyFieldlist(typeptr, subtype);
- }
- break;
- case LF_UNION_32:
- if( type->t_union32.un_len >= 0x8000 )
- {
- /*
- * This is a numeric leaf, I am too lazy to handle this right
- * now.
- */
- DEBUG_Printf(DBG_CHN_MESG, "Ignoring large numberic leaf.\n");
- break;
- }
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->t_union32.name, type->t_union32.namelen);
-
- if( strcmp(symname, "__unnamed") == 0 )
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, NULL);
- }
- else
- {
- typeptr = DEBUG_NewDataType(DT_STRUCT, symname);
- }
-
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- /*
- * Now copy the relevant bits from the fieldlist that we specified.
- */
- subtype = DEBUG_GetCVType(type->t_union32.field);
-
- if( subtype != NULL )
- {
- DEBUG_SetStructSize(typeptr, type->t_union32.un_len);
- DEBUG_CopyFieldlist(typeptr, subtype);
- }
- break;
- case LF_BITFIELD:
- typeptr = DEBUG_NewDataType(DT_BITFIELD, NULL);
- cv_defined_types[curr_type - 0x1000] = typeptr;
- DEBUG_SetBitfieldParams(typeptr, type->bitfield.bitoff,
- type->bitfield.nbits,
- DEBUG_GetCVType(type->bitfield.type));
- break;
- case LF_BITFIELD_32:
- typeptr = DEBUG_NewDataType(DT_BITFIELD, NULL);
- cv_defined_types[curr_type - 0x1000] = typeptr;
- DEBUG_SetBitfieldParams(typeptr, type->bitfield32.bitoff,
- type->bitfield32.nbits,
- DEBUG_GetCVType(type->bitfield32.type));
- break;
- case LF_ENUM:
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->enumeration.name, type->enumeration.namelen);
- typeptr = DEBUG_NewDataType(DT_ENUM, symname);
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- /*
- * Now copy the relevant bits from the fieldlist that we specified.
- */
- subtype = DEBUG_GetCVType(type->enumeration.field);
-
- if( subtype != NULL )
- {
- DEBUG_CopyFieldlist(typeptr, subtype);
- }
- break;
- case LF_ENUM_32:
- memset(symname, 0, sizeof(symname));
- memcpy(symname, type->enumeration32.name, type->enumeration32.namelen);
- typeptr = DEBUG_NewDataType(DT_ENUM, symname);
- cv_defined_types[curr_type - 0x1000] = typeptr;
-
- /*
- * Now copy the relevant bits from the fieldlist that we specified.
- */
- subtype = DEBUG_GetCVType(type->enumeration32.field);
-
- if( subtype != NULL )
- {
- DEBUG_CopyFieldlist(typeptr, subtype);
- }
- break;
- default:
- break;
- }
- curr_type++;
- ptr.c += (type->generic.len + 3) & ~3;
+ if ( cv_defined_types == NULL )
+ return FALSE;
}
- return TRUE;
+ cv_defined_types[ typeno - 0x1000 ] = dt;
+ return TRUE;
}
+static void
+DEBUG_ClearTypeTable( void )
+{
+ if ( cv_defined_types )
+ DBG_free( cv_defined_types );
+
+ cv_defined_types = NULL;
+ num_cv_defined_types = 0;
+}
+
+static int
+DEBUG_AddCVType_Pointer( unsigned int typeno, unsigned int datatype )
+{
+ struct datatype *dt =
+ DEBUG_FindOrMakePointerType( DEBUG_GetCVType( datatype ) );
+
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_AddCVType_Array( unsigned int typeno, char *name,
+ unsigned int elemtype, unsigned int arr_len )
+{
+ struct datatype *dt = DEBUG_NewDataType( DT_ARRAY, name );
+ struct datatype *elem = DEBUG_GetCVType( elemtype );
+ unsigned int elem_size = elem? DEBUG_GetObjectSize( elem ) : 0;
+ unsigned int arr_max = elem_size? arr_len / elem_size : 0;
+
+ DEBUG_SetArrayParams( dt, 0, arr_max, elem );
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_AddCVType_Bitfield( unsigned int typeno,
+ unsigned int bitoff, unsigned int nbits,
+ unsigned int basetype )
+{
+ struct datatype *dt = DEBUG_NewDataType( DT_BITFIELD, NULL );
+ struct datatype *base = DEBUG_GetCVType( basetype );
+
+ DEBUG_SetBitfieldParams( dt, bitoff, nbits, base );
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_AddCVType_EnumFieldList( unsigned int typeno, unsigned char *list, int len )
+{
+ struct datatype *dt = DEBUG_NewDataType( DT_ENUM, NULL );
+ unsigned char *ptr = list;
+
+ while ( ptr - list < len )
+ {
+ union codeview_fieldtype *type = (union codeview_fieldtype *)ptr;
+
+ if ( *ptr >= 0xf0 ) /* LF_PAD... */
+ {
+ ptr += *ptr & 0x0f;
+ continue;
+ }
+
+ switch ( type->generic.id )
+ {
+ case LF_ENUMERATE:
+ {
+ int value, vlen = numeric_leaf( &value, &type->enumerate.value );
+ unsigned char *name = (unsigned char *)&type->enumerate.value + vlen;
+
+ DEBUG_AddStructElement( dt, terminate_string( name ),
+ NULL, value, 0 );
+
+ ptr += 2 + 2 + vlen + (1 + name[0]);
+ break;
+ }
+
+ default:
+ DEBUG_Printf( DBG_CHN_MESG, "Unhandled type %04x in ENUM field list\n",
+ type->generic.id );
+ return FALSE;
+ }
+ }
+
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_AddCVType_StructFieldList( unsigned int typeno, unsigned char *list, int len )
+{
+ struct datatype *dt = DEBUG_NewDataType( DT_STRUCT, NULL );
+ unsigned char *ptr = list;
+
+ while ( ptr - list < len )
+ {
+ union codeview_fieldtype *type = (union codeview_fieldtype *)ptr;
+
+ if ( *ptr >= 0xf0 ) /* LF_PAD... */
+ {
+ ptr += *ptr & 0x0f;
+ continue;
+ }
+
+ switch ( type->generic.id )
+ {
+ case LF_BCLASS:
+ {
+ int offset, olen = numeric_leaf( &offset, &type->bclass.offset );
+
+ /* FIXME: ignored for now */
+
+ ptr += 2 + 2 + 2 + olen;
+ break;
+ }
+
+ case LF_BCLASS_32:
+ {
+ int offset, olen = numeric_leaf( &offset, &type->bclass32.offset );
+
+ /* FIXME: ignored for now */
+
+ ptr += 2 + 2 + 4 + olen;
+ break;
+ }
+
+ case LF_VBCLASS:
+ case LF_IVBCLASS:
+ {
+ int vbpoff, vbplen = numeric_leaf( &vbpoff, &type->vbclass.vbpoff );
+ unsigned short int *p_vboff = (unsigned short int *)((char *)&type->vbclass.vbpoff + vbpoff);
+ int vpoff, vplen = numeric_leaf( &vpoff, p_vboff );
+
+ /* FIXME: ignored for now */
+
+ ptr += 2 + 2 + 2 + 2 + vbplen + vplen;
+ break;
+ }
+
+ case LF_VBCLASS_32:
+ case LF_IVBCLASS_32:
+ {
+ int vbpoff, vbplen = numeric_leaf( &vbpoff, &type->vbclass32.vbpoff );
+ unsigned short int *p_vboff = (unsigned short int *)((char *)&type->vbclass32.vbpoff + vbpoff);
+ int vpoff, vplen = numeric_leaf( &vpoff, p_vboff );
+
+ /* FIXME: ignored for now */
+
+ ptr += 2 + 2 + 4 + 4 + vbplen + vplen;
+ break;
+ }
+
+ case LF_MEMBER:
+ {
+ int offset, olen = numeric_leaf( &offset, &type->member.offset );
+ unsigned char *name = (unsigned char *)&type->member.offset + olen;
+
+ struct datatype *subtype = DEBUG_GetCVType( type->member.type );
+ int elem_size = subtype? DEBUG_GetObjectSize( subtype ) : 0;
+
+ DEBUG_AddStructElement( dt, terminate_string( name ),
+ subtype, offset << 3, elem_size << 3 );
+
+ ptr += 2 + 2 + 2 + olen + (1 + name[0]);
+ break;
+ }
+
+ case LF_MEMBER_32:
+ {
+ int offset, olen = numeric_leaf( &offset, &type->member32.offset );
+ unsigned char *name = (unsigned char *)&type->member32.offset + olen;
+
+ struct datatype *subtype = DEBUG_GetCVType( type->member32.type );
+ int elem_size = subtype? DEBUG_GetObjectSize( subtype ) : 0;
+
+ DEBUG_AddStructElement( dt, terminate_string( name ),
+ subtype, offset << 3, elem_size << 3 );
+
+ ptr += 2 + 2 + 4 + olen + (1 + name[0]);
+ break;
+ }
+
+ case LF_STMEMBER:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2 + 2 + (1 + type->stmember.name[0]);
+ break;
+
+ case LF_STMEMBER_32:
+ /* FIXME: ignored for now */
+ ptr += 2 + 4 + 2 + (1 + type->stmember32.name[0]);
+ break;
+
+ case LF_METHOD:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2 + 2 + (1 + type->method.name[0]);
+ break;
+
+ case LF_METHOD_32:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2 + 4 + (1 + type->method32.name[0]);
+ break;
+
+ case LF_NESTTYPE:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2 + (1 + type->nesttype.name[0]);
+ break;
+
+ case LF_NESTTYPE_32:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2 + 4 + (1 + type->nesttype32.name[0]);
+ break;
+
+ case LF_VFUNCTAB:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2;
+ break;
+
+ case LF_VFUNCTAB_32:
+ /* FIXME: ignored for now */
+ ptr += 2 + 2 + 4;
+ break;
+
+ case LF_ONEMETHOD:
+ /* FIXME: ignored for now */
+ switch ( (type->onemethod.attribute >> 2) & 7 )
+ {
+ case 4: case 6: /* (pure) introducing virtual method */
+ ptr += 2 + 2 + 2 + 4 + (1 + type->onemethod_virt.name[0]);
+ break;
+
+ default:
+ ptr += 2 + 2 + 2 + (1 + type->onemethod.name[0]);
+ break;
+ }
+ break;
+
+ case LF_ONEMETHOD_32:
+ /* FIXME: ignored for now */
+ switch ( (type->onemethod32.attribute >> 2) & 7 )
+ {
+ case 4: case 6: /* (pure) introducing virtual method */
+ ptr += 2 + 2 + 4 + 4 + (1 + type->onemethod32_virt.name[0]);
+ break;
+
+ default:
+ ptr += 2 + 2 + 4 + (1 + type->onemethod32.name[0]);
+ break;
+ }
+ break;
+
+ default:
+ DEBUG_Printf( DBG_CHN_MESG, "Unhandled type %04x in STRUCT field list\n",
+ type->generic.id );
+ return FALSE;
+ }
+ }
+
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_AddCVType_Enum( unsigned int typeno, char *name, unsigned int fieldlist )
+{
+ struct datatype *dt = DEBUG_NewDataType( DT_ENUM, name );
+ struct datatype *list = DEBUG_GetCVType( fieldlist );
+
+ if ( list )
+ DEBUG_CopyFieldlist( dt, list );
+
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_AddCVType_Struct( unsigned int typeno, char *name, int structlen, unsigned int fieldlist )
+{
+ struct datatype *dt = DEBUG_NewDataType( DT_STRUCT, name );
+ struct datatype *list = DEBUG_GetCVType( fieldlist );
+
+ if ( list )
+ {
+ DEBUG_SetStructSize( dt, structlen );
+ DEBUG_CopyFieldlist( dt, list );
+ }
+
+ return DEBUG_AddCVType( typeno, dt );
+}
+
+static int
+DEBUG_ParseTypeTable( char *table, int len )
+{
+ unsigned int curr_type = 0x1000;
+ char *ptr = table;
+
+ while ( ptr - table < len )
+ {
+ union codeview_type *type = (union codeview_type *) ptr;
+ int retv = TRUE;
+
+ switch ( type->generic.id )
+ {
+ case LF_POINTER:
+ retv = DEBUG_AddCVType_Pointer( curr_type, type->pointer.datatype );
+ break;
+ case LF_POINTER_32:
+ retv = DEBUG_AddCVType_Pointer( curr_type, type->pointer32.datatype );
+ break;
+
+ case LF_ARRAY:
+ {
+ int arrlen, alen = numeric_leaf( &arrlen, &type->array.arrlen );
+ unsigned char *name = (unsigned char *)&type->array.arrlen + alen;
+
+ retv = DEBUG_AddCVType_Array( curr_type, terminate_string( name ),
+ type->array.elemtype, arrlen );
+ break;
+ }
+ case LF_ARRAY_32:
+ {
+ int arrlen, alen = numeric_leaf( &arrlen, &type->array32.arrlen );
+ unsigned char *name = (unsigned char *)&type->array32.arrlen + alen;
+
+ retv = DEBUG_AddCVType_Array( curr_type, terminate_string( name ),
+ type->array32.elemtype, type->array32.arrlen );
+ break;
+ }
+
+ case LF_BITFIELD:
+ retv = DEBUG_AddCVType_Bitfield( curr_type, type->bitfield.bitoff,
+ type->bitfield.nbits,
+ type->bitfield.type );
+ break;
+ case LF_BITFIELD_32:
+ retv = DEBUG_AddCVType_Bitfield( curr_type, type->bitfield32.bitoff,
+ type->bitfield32.nbits,
+ type->bitfield32.type );
+ break;
+
+ case LF_FIELDLIST:
+ case LF_FIELDLIST_32:
+ {
+ /*
+ * 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.
+ */
+
+ char *list = type->fieldlist.list;
+ int len = (ptr + type->generic.len + 2) - list;
+
+ if ( ((union codeview_fieldtype *)list)->generic.id == LF_ENUMERATE )
+ retv = DEBUG_AddCVType_EnumFieldList( curr_type, list, len );
+ else
+ retv = DEBUG_AddCVType_StructFieldList( curr_type, list, len );
+ break;
+ }
+
+ case LF_STRUCTURE:
+ case LF_CLASS:
+ {
+ int structlen, slen = numeric_leaf( &structlen, &type->structure.structlen );
+ unsigned char *name = (unsigned char *)&type->structure.structlen + slen;
+
+ retv = DEBUG_AddCVType_Struct( curr_type, terminate_string( name ),
+ structlen, type->structure.fieldlist );
+ break;
+ }
+ case LF_STRUCTURE_32:
+ case LF_CLASS_32:
+ {
+ int structlen, slen = numeric_leaf( &structlen, &type->structure32.structlen );
+ unsigned char *name = (unsigned char *)&type->structure32.structlen + slen;
+
+ retv = DEBUG_AddCVType_Struct( curr_type, terminate_string( name ),
+ structlen, type->structure32.fieldlist );
+ break;
+ }
+
+ case LF_UNION:
+ {
+ int un_len, ulen = numeric_leaf( &un_len, &type->t_union.un_len );
+ unsigned char *name = (unsigned char *)&type->t_union.un_len + ulen;
+
+ retv = DEBUG_AddCVType_Struct( curr_type, terminate_string( name ),
+ un_len, type->t_union.fieldlist );
+ break;
+ }
+ case LF_UNION_32:
+ {
+ int un_len, ulen = numeric_leaf( &un_len, &type->t_union32.un_len );
+ unsigned char *name = (unsigned char *)&type->t_union32.un_len + ulen;
+
+ retv = DEBUG_AddCVType_Struct( curr_type, terminate_string( name ),
+ un_len, type->t_union32.fieldlist );
+ break;
+ }
+
+ case LF_ENUM:
+ retv = DEBUG_AddCVType_Enum( curr_type, terminate_string( type->enumeration.name ),
+ type->enumeration.field );
+ break;
+ case LF_ENUM_32:
+ retv = DEBUG_AddCVType_Enum( curr_type, terminate_string( type->enumeration32.name ),
+ type->enumeration32.field );
+ break;
+
+ default:
+ break;
+ }
+
+ if ( !retv )
+ return FALSE;
+
+ curr_type++;
+ ptr += type->generic.len + 2;
+ }
+
+ return TRUE;
+}
+
+
void
DEBUG_InitCVDataTypes(void)
{
@@ -2733,6 +3052,8 @@
* Cleanup
*/
+ DEBUG_ClearTypeTable();
+
if ( symbols_image ) pdb_free( symbols_image );
if ( types_image ) pdb_free( types_image );
if ( root ) pdb_free( root );