dbghelp: MSC forward declaration.

- create an infrastructure for handling forward usage
  of type records
- used it in some cases (pointer to yet not defined udt,
  function signature, modifiers)
This commit is contained in:
Eric Pouech 2006-03-18 13:33:11 +01:00 committed by Alexandre Julliard
parent 79b47204f0
commit e737dbec7f
1 changed files with 231 additions and 112 deletions

View File

@ -355,7 +355,11 @@ static int codeview_add_type(unsigned int typeno, struct symt* dt)
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(void)
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)
{
return &symt_new_pointer(module,
codeview_get_type(datatype, FALSE))->symt;
if (symt->tag != tag)
{
FIXME("Bad tag. Expected %d, but got %d\n", tag, symt->tag);
return NULL;
}
return symt;
}
static struct symt* codeview_add_type_array(struct module* module,
static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp,
unsigned typeno)
{
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_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_array(struct module* module,
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,14 +496,31 @@ static int codeview_add_type_enum_field_list(struct module* module,
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);
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_fetch_type(ctp, cv_type->bitfield_v1.type),
cv_type->bitfield_v1.bitoff,
cv_type->bitfield_v1.nbits);
return;
case LF_BITFIELD_V2:
symt_add_udt_element(ctp->module, symt, name,
codeview_fetch_type(ctp, cv_type->bitfield_v2.type),
cv_type->bitfield_v2.bitoff,
cv_type->bitfield_v2.nbits);
return;
}
}
subtype = codeview_fetch_type(ctp, type);
/* FIXME: we expect no forward usage of subtypes */
if (subtype)
{
DWORD64 elem_size = 0;
@ -465,39 +528,25 @@ static void codeview_add_udt_element(struct codeview_type_parse* ctp,
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)))
{
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),
cv_type->bitfield_v1.bitoff,
cv_type->bitfield_v1.nbits);
break;
case LF_BITFIELD_V2:
symt_add_udt_element(ctp->module, symt, name,
codeview_get_type(cv_type->bitfield_v2.type, FALSE),
cv_type->bitfield_v2.bitoff,
cv_type->bitfield_v2.nbits);
break;
default:
FIXME("Unexpected leaf %x\n", cv_type->generic.id);
}
}
}
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_field_list(struct codeview_type_parse* ctp,
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_signature(struct codeview_type_parse* ctp,
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_signature(struct codeview_type_parse* ctp,
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_signature(struct codeview_type_parse* ctp,
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_type(struct codeview_type_parse* ctp,
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_type(struct codeview_type_parse* ctp,
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(struct codeview_type_parse* ctp)
* 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;