dbghelp: First stab at supporting calling convention in function signature.
This commit is contained in:
parent
750575ccf2
commit
be849decf6
|
@ -220,6 +220,7 @@ struct symt_function_signature
|
||||||
struct symt symt;
|
struct symt symt;
|
||||||
struct symt* rettype;
|
struct symt* rettype;
|
||||||
struct vector vchildren;
|
struct vector vchildren;
|
||||||
|
enum CV_call_e call_conv;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct symt_function_arg_type
|
struct symt_function_arg_type
|
||||||
|
@ -472,7 +473,8 @@ extern struct symt_array*
|
||||||
struct symt* base);
|
struct symt* base);
|
||||||
extern struct symt_function_signature*
|
extern struct symt_function_signature*
|
||||||
symt_new_function_signature(struct module* module,
|
symt_new_function_signature(struct module* module,
|
||||||
struct symt* ret_type);
|
struct symt* ret_type,
|
||||||
|
enum CV_call_e call_conv);
|
||||||
extern BOOL symt_add_function_signature_parameter(struct module* module,
|
extern BOOL symt_add_function_signature_parameter(struct module* module,
|
||||||
struct symt_function_signature* sig,
|
struct symt_function_signature* sig,
|
||||||
struct symt* param);
|
struct symt* param);
|
||||||
|
|
|
@ -443,6 +443,17 @@ typedef enum dwarf_operation_e {
|
||||||
DW_OP_nop = 0x96
|
DW_OP_nop = 0x96
|
||||||
} dwarf_operation_t;
|
} dwarf_operation_t;
|
||||||
|
|
||||||
|
enum dwarf_calling_convention
|
||||||
|
{
|
||||||
|
DW_CC_normal = 0x1,
|
||||||
|
DW_CC_program = 0x2,
|
||||||
|
DW_CC_nocall = 0x3
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DW_CC_lo_user 0x40
|
||||||
|
#define DW_CC_hi_user 0xff
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parsers
|
* Parsers
|
||||||
*/
|
*/
|
||||||
|
@ -1876,6 +1887,8 @@ static struct symt_function* dwarf2_parse_subprogram(struct module* module, dwar
|
||||||
unsigned char decl_line = 0;
|
unsigned char decl_line = 0;
|
||||||
dwarf2_abbrev_entry_attr_t* attr = NULL;
|
dwarf2_abbrev_entry_attr_t* attr = NULL;
|
||||||
unsigned long next_sibling = 0;
|
unsigned long next_sibling = 0;
|
||||||
|
enum CV_call_e call_conv = CV_CALL_FAR_C; /* FIXME: assuming C source code */
|
||||||
|
unsigned cc;
|
||||||
|
|
||||||
TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code);
|
TRACE("%s, for %lu\n", dwarf2_debug_ctx(ctx), entry->entry_code);
|
||||||
|
|
||||||
|
@ -1908,6 +1921,14 @@ static struct symt_function* dwarf2_parse_subprogram(struct module* module, dwar
|
||||||
case DW_AT_inline:
|
case DW_AT_inline:
|
||||||
inl_flags = dwarf2_parse_byte(ctx);
|
inl_flags = dwarf2_parse_byte(ctx);
|
||||||
break;
|
break;
|
||||||
|
case DW_AT_calling_convention:
|
||||||
|
switch (cc = dwarf2_parse_byte(ctx))
|
||||||
|
{
|
||||||
|
case DW_CC_normal: break;
|
||||||
|
case DW_CC_nocall: call_conv = -1;
|
||||||
|
default: FIXME("Unsupported calling convention %d\n", cc);
|
||||||
|
}
|
||||||
|
break;
|
||||||
/* not work yet, need parsing .debug_line and using Compil Unit stmt_list
|
/* not work yet, need parsing .debug_line and using Compil Unit stmt_list
|
||||||
case DW_AT_decl_file:
|
case DW_AT_decl_file:
|
||||||
decl_file = dwarf2_parse_byte(ctx);
|
decl_file = dwarf2_parse_byte(ctx);
|
||||||
|
@ -1921,7 +1942,7 @@ static struct symt_function* dwarf2_parse_subprogram(struct module* module, dwar
|
||||||
dwarf2_parse_attr(attr, ctx);
|
dwarf2_parse_attr(attr, ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sig_type = symt_new_function_signature(module, ret_type);
|
sig_type = symt_new_function_signature(module, ret_type, call_conv);
|
||||||
if (!is_decl) {
|
if (!is_decl) {
|
||||||
func_type = symt_new_function(module, compiland, name, addr, size, &sig_type->symt);
|
func_type = symt_new_function(module, compiland, name, addr, size, &sig_type->symt);
|
||||||
if (low_pc && high_pc) {
|
if (low_pc && high_pc) {
|
||||||
|
|
|
@ -726,11 +726,12 @@ static int codeview_add_type_struct(struct module* module, unsigned int typeno,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int codeview_new_func_signature(struct module* module, unsigned typeno,
|
static int codeview_new_func_signature(struct module* module, unsigned typeno,
|
||||||
unsigned ret_type)
|
unsigned ret_type, enum CV_call_e call_conv)
|
||||||
{
|
{
|
||||||
struct symt* symt;
|
struct symt* symt;
|
||||||
symt = &symt_new_function_signature(module,
|
symt = &symt_new_function_signature(module,
|
||||||
codeview_get_type(ret_type, FALSE))->symt;
|
codeview_get_type(ret_type, FALSE),
|
||||||
|
call_conv)->symt;
|
||||||
return codeview_add_type(typeno, symt);
|
return codeview_add_type(typeno, symt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,25 +917,29 @@ static int codeview_parse_type_table(struct module* module, const BYTE* table,
|
||||||
break;
|
break;
|
||||||
case LF_PROCEDURE_V1:
|
case LF_PROCEDURE_V1:
|
||||||
retv = codeview_new_func_signature(module, curr_type,
|
retv = codeview_new_func_signature(module, curr_type,
|
||||||
type->procedure_v1.rvtype);
|
type->procedure_v1.rvtype,
|
||||||
|
type->procedure_v1.call);
|
||||||
break;
|
break;
|
||||||
case LF_PROCEDURE_V2:
|
case LF_PROCEDURE_V2:
|
||||||
retv = codeview_new_func_signature(module, curr_type,
|
retv = codeview_new_func_signature(module, curr_type,
|
||||||
type->procedure_v2.rvtype);
|
type->procedure_v2.rvtype,
|
||||||
|
type->procedure_v2.call);
|
||||||
break;
|
break;
|
||||||
case LF_MFUNCTION_V1:
|
case LF_MFUNCTION_V1:
|
||||||
/* FIXME: for C++, this is plain wrong, but as we don't use arg types
|
/* FIXME: for C++, this is plain wrong, but as we don't use arg types
|
||||||
* nor class information, this would just do for now
|
* nor class information, this would just do for now
|
||||||
*/
|
*/
|
||||||
retv = codeview_new_func_signature(module, curr_type,
|
retv = codeview_new_func_signature(module, curr_type,
|
||||||
type->mfunction_v1.rvtype);
|
type->mfunction_v1.rvtype,
|
||||||
|
type->mfunction_v1.call);
|
||||||
break;
|
break;
|
||||||
case LF_MFUNCTION_V2:
|
case LF_MFUNCTION_V2:
|
||||||
/* FIXME: for C++, this is plain wrong, but as we don't use arg types
|
/* FIXME: for C++, this is plain wrong, but as we don't use arg types
|
||||||
* nor class information, this would just do for now
|
* nor class information, this would just do for now
|
||||||
*/
|
*/
|
||||||
retv = codeview_new_func_signature(module, curr_type,
|
retv = codeview_new_func_signature(module, curr_type,
|
||||||
type->mfunction_v2.rvtype);
|
type->mfunction_v2.rvtype,
|
||||||
|
type->mfunction_v2.call);
|
||||||
break;
|
break;
|
||||||
case LF_ARGLIST_V1:
|
case LF_ARGLIST_V1:
|
||||||
case LF_ARGLIST_V2:
|
case LF_ARGLIST_V2:
|
||||||
|
|
|
@ -848,7 +848,7 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
|
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
|
||||||
new_dt = &symt_new_function_signature(ptd->module, ref_dt)->symt;
|
new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
new_dt = &symt_new_enum(ptd->module, typename)->symt;
|
new_dt = &symt_new_enum(ptd->module, typename)->symt;
|
||||||
|
@ -930,7 +930,7 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ
|
||||||
{
|
{
|
||||||
ptd->ptr++;
|
ptd->ptr++;
|
||||||
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
|
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
|
||||||
new_dt = &symt_new_function_signature(ptd->module, ref_dt)->symt;
|
new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -940,7 +940,7 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ
|
||||||
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &cls_dt) == -1);
|
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &cls_dt) == -1);
|
||||||
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
|
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
|
||||||
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
|
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref_dt) == -1);
|
||||||
new_dt = &symt_new_function_signature(ptd->module, ref_dt)->symt;
|
new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt;
|
||||||
while (*ptd->ptr == ',')
|
while (*ptd->ptr == ',')
|
||||||
{
|
{
|
||||||
ptd->ptr++;
|
ptd->ptr++;
|
||||||
|
@ -1422,7 +1422,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
|
||||||
(load_offset + stab_ptr->n_value - curr_func->address) : 0);
|
(load_offset + stab_ptr->n_value - curr_func->address) : 0);
|
||||||
}
|
}
|
||||||
func_type = symt_new_function_signature(module,
|
func_type = symt_new_function_signature(module,
|
||||||
stabs_parse_type(ptr));
|
stabs_parse_type(ptr), -1);
|
||||||
curr_func = symt_new_function(module, compiland, symname,
|
curr_func = symt_new_function(module, compiland, symname,
|
||||||
load_offset + stab_ptr->n_value, 0,
|
load_offset + stab_ptr->n_value, 0,
|
||||||
&func_type->symt);
|
&func_type->symt);
|
||||||
|
|
|
@ -298,7 +298,8 @@ struct symt_array* symt_new_array(struct module* module, int min, int max,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct symt_function_signature* symt_new_function_signature(struct module* module,
|
struct symt_function_signature* symt_new_function_signature(struct module* module,
|
||||||
struct symt* ret_type)
|
struct symt* ret_type,
|
||||||
|
enum CV_call_e call_conv)
|
||||||
{
|
{
|
||||||
struct symt_function_signature* sym;
|
struct symt_function_signature* sym;
|
||||||
|
|
||||||
|
@ -307,6 +308,7 @@ struct symt_function_signature* symt_new_function_signature(struct module* modul
|
||||||
sym->symt.tag = SymTagFunctionType;
|
sym->symt.tag = SymTagFunctionType;
|
||||||
sym->rettype = ret_type;
|
sym->rettype = ret_type;
|
||||||
vector_init(&sym->vchildren, sizeof(struct symt*), 4);
|
vector_init(&sym->vchildren, sizeof(struct symt*), 4);
|
||||||
|
sym->call_conv = call_conv;
|
||||||
symt_add_type(module, &sym->symt);
|
symt_add_type(module, &sym->symt);
|
||||||
}
|
}
|
||||||
return sym;
|
return sym;
|
||||||
|
@ -735,11 +737,20 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
||||||
X(VARIANT) = ((const struct symt_data*)type)->u.value;
|
X(VARIANT) = ((const struct symt_data*)type)->u.value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TI_GET_CALLING_CONVENTION:
|
||||||
|
if (type->tag != SymTagFunctionType) return FALSE;
|
||||||
|
if (((const struct symt_function_signature*)type)->call_conv == -1)
|
||||||
|
{
|
||||||
|
FIXME("No support for calling convention for this signature\n");
|
||||||
|
X(DWORD) = CV_CALL_FAR_C; /* FIXME */
|
||||||
|
}
|
||||||
|
else X(DWORD) = ((const struct symt_function_signature*)type)->call_conv;
|
||||||
|
break;
|
||||||
|
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
case TI_GET_ADDRESSOFFSET:
|
case TI_GET_ADDRESSOFFSET:
|
||||||
case TI_GET_ARRAYINDEXTYPEID:
|
case TI_GET_ARRAYINDEXTYPEID:
|
||||||
case TI_GET_CALLING_CONVENTION:
|
|
||||||
case TI_GET_CLASSPARENTID:
|
case TI_GET_CLASSPARENTID:
|
||||||
case TI_GET_SYMINDEX:
|
case TI_GET_SYMINDEX:
|
||||||
case TI_GET_THISADJUST:
|
case TI_GET_THISADJUST:
|
||||||
|
@ -749,6 +760,9 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
|
||||||
case TI_IS_EQUIV_TO:
|
case TI_IS_EQUIV_TO:
|
||||||
FIXME("Unsupported GetInfo request (%u)\n", req);
|
FIXME("Unsupported GetInfo request (%u)\n", req);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
default:
|
||||||
|
FIXME("Unknown GetInfo request (%u)\n", req);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in New Issue