dbghelp: Dwarf & function blocks.

- properly handling function blocks
- handling of variables inside of blocks (either on stack, or in a
  register, or relative to the frame register if any)
- added dwarf2_subprogram_t structure so that we can pass around
  relevant information for function parsing
This commit is contained in:
Eric Pouech 2006-06-18 21:32:03 +02:00 committed by Alexandre Julliard
parent 7476f8c840
commit a2b4432107
1 changed files with 127 additions and 74 deletions

View File

@ -55,11 +55,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_dwarf);
/* FIXME:
* - Functions:
* o local variables
* o unspecified parameters
* o inlined functions
* o line numbers
* o Debug{Start|End}Point
* o CFA
* - Udt
* o proper types loading (addresses, bitfield, nesting)
*/
@ -941,30 +941,15 @@ static struct symt* dwarf2_parse_enumeration_type(dwarf2_parse_context_t* ctx,
return di->symt;
}
static void dwarf2_parse_variable(dwarf2_parse_context_t* ctx,
dwarf2_debug_info_t* di)
{
struct symt* var_type;
union attribute name;
TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
var_type = dwarf2_lookup_type(ctx, di);
dwarf2_find_name(ctx, di, &name, "variable");
/* FIXME: still lots to do !!! */
if (di->abbrev->have_child) FIXME("Unsupported children\n");
}
static unsigned dwarf2_map_register(int regno)
{
unsigned reg;
switch (regno)
{
case -1:
case Wine_DW_no_register: FIXME("What the heck\n"); reg = 0; break;
/* FIXME: this is a dirty hack */
case -2: reg = 0; break;
case Wine_DW_frame_register: reg = 0; break;
case 0: reg = CV_REG_EAX; break;
case 1: reg = CV_REG_ECX; break;
case 2: reg = CV_REG_EDX; break;
@ -1005,63 +990,101 @@ reg: fop 31
return reg;
}
static void dwarf2_parse_subprogram_parameter(dwarf2_parse_context_t* ctx,
struct symt_function* func,
struct symt_block* block,
dwarf2_debug_info_t* di)
/* structure used to pass information around when parsing a subprogram */
typedef struct dwarf2_subprogram_s
{
dwarf2_parse_context_t* ctx;
struct symt_compiland* compiland;
struct symt_function* func;
long frame_offset;
int frame_reg;
} dwarf2_subprogram_t;
/******************************************************************
* dwarf2_parse_variable
*
* Parses any variable (parameter, local/global variable)
*/
static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
struct symt_block* block,
dwarf2_debug_info_t* di)
{
struct symt* param_type;
union attribute loc;
BOOL is_pmt = di->abbrev->tag == DW_TAG_formal_parameter;
TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
param_type = dwarf2_lookup_type(ctx, di);
param_type = dwarf2_lookup_type(subpgm->ctx, di);
if (dwarf2_find_attribute(di, DW_AT_location, &loc))
{
union attribute name;
unsigned long offset;
union attribute ext;
long offset;
int in_reg;
dwarf2_find_name(ctx, di, &name, "parameter");
offset = dwarf2_compute_location(ctx, loc.block, &in_reg);
dwarf2_find_name(subpgm->ctx, di, &name, "parameter");
offset = dwarf2_compute_location(subpgm->ctx, loc.block, &in_reg);
TRACE("found parameter %s/%ld (reg=%d) at %s\n",
name.string, offset, in_reg, dwarf2_debug_ctx(ctx));
symt_add_func_local(ctx->module, func,
DataIsParam, dwarf2_map_register(in_reg), offset,
block, param_type, name.string);
name.string, offset, in_reg, dwarf2_debug_ctx(subpgm->ctx));
switch (in_reg)
{
case Wine_DW_no_register:
/* it's a global variable */
/* FIXME: we don't handle it's scope yet */
if (!dwarf2_find_attribute(di, DW_AT_external, &ext))
ext.uvalue = 0;
symt_new_global_variable(subpgm->ctx->module, subpgm->compiland,
name.string, !ext.uvalue,
subpgm->ctx->module->module.BaseOfImage + offset,
0, param_type);
break;
case Wine_DW_frame_register:
in_reg = subpgm->frame_reg;
offset += subpgm->frame_offset;
/* fall through */
default:
/* either a pmt/variable relative to frame pointer or
* pmt/variable in a register
*/
symt_add_func_local(subpgm->ctx->module, subpgm->func,
is_pmt ? DataIsParam : DataIsLocal,
dwarf2_map_register(in_reg), offset,
block, param_type, name.string);
break;
}
}
if (func && func->type)
symt_add_function_signature_parameter(ctx->module,
(struct symt_function_signature*)func->type,
if (is_pmt && subpgm->func && subpgm->func->type)
symt_add_function_signature_parameter(subpgm->ctx->module,
(struct symt_function_signature*)subpgm->func->type,
param_type);
if (di->abbrev->have_child) FIXME("Unsupported children\n");
}
static void dwarf2_parse_subprogram_label(dwarf2_parse_context_t* ctx,
struct symt_function* func,
static void dwarf2_parse_subprogram_label(dwarf2_subprogram_t* subpgm,
dwarf2_debug_info_t* di)
{
union attribute name;
union attribute low_pc;
TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc)) low_pc.uvalue = 0;
dwarf2_find_name(ctx, di, &name, "label");
dwarf2_find_name(subpgm->ctx, di, &name, "label");
symt_add_function_point(ctx->module, func, SymTagLabel,
ctx->module->module.BaseOfImage + low_pc.uvalue, name.string);
symt_add_function_point(subpgm->ctx->module, subpgm->func, SymTagLabel,
subpgm->ctx->module->module.BaseOfImage + low_pc.uvalue, name.string);
}
static void dwarf2_parse_subprogram_block(dwarf2_parse_context_t* ctx,
dwarf2_debug_info_t* di,
struct symt_function* func);
static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
struct symt_block* block_parent,
dwarf2_debug_info_t* di);
static void dwarf2_parse_inlined_subroutine(dwarf2_parse_context_t* ctx,
static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm,
dwarf2_debug_info_t* di)
{
TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
/* FIXME: attributes to handle:
DW_AT_low_pc:
@ -1086,7 +1109,9 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_parse_context_t* ctx,
*/
break;
case DW_TAG_variable:
dwarf2_parse_variable(ctx, child);
/* FIXME:
* dwarf2_parse_variable(ctx, child);
*/
break;
case DW_TAG_lexical_block:
/* FIXME:
@ -1095,28 +1120,35 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_parse_context_t* ctx,
break;
case DW_TAG_inlined_subroutine:
/* FIXME */
dwarf2_parse_inlined_subroutine(ctx, child);
dwarf2_parse_inlined_subroutine(subpgm, child);
break;
case DW_TAG_label:
/* FIXME
* dwarf2_parse_subprogram_label(ctx, func, child);
*/
dwarf2_parse_subprogram_label(subpgm, child);
break;
default:
FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx),
dwarf2_debug_di(di));
}
}
}
}
static void dwarf2_parse_subprogram_block(dwarf2_parse_context_t* ctx,
dwarf2_debug_info_t* di,
struct symt_function* func)
static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
struct symt_block* parent_block,
dwarf2_debug_info_t* di)
{
TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
struct symt_block* block;
union attribute low_pc;
union attribute high_pc;
/* if (!dwarf2_find_attribute(di, DW_AT_ranges, ??)): what to do ? */
TRACE("%s, for %s\n", dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc)) low_pc.uvalue = 0;
if (!dwarf2_find_attribute(di, DW_AT_high_pc, &high_pc)) high_pc.uvalue = 0;
block = symt_open_func_block(subpgm->ctx->module, subpgm->func, parent_block,
low_pc.uvalue, high_pc.uvalue - low_pc.uvalue);
if (di->abbrev->have_child) /** any interest to not have child ? */
{
@ -1130,19 +1162,24 @@ static void dwarf2_parse_subprogram_block(dwarf2_parse_context_t* ctx,
switch (child->abbrev->tag)
{
case DW_TAG_inlined_subroutine:
dwarf2_parse_inlined_subroutine(ctx, child);
dwarf2_parse_inlined_subroutine(subpgm, child);
break;
case DW_TAG_variable:
dwarf2_parse_variable(ctx, child);
dwarf2_parse_variable(subpgm, block, child);
break;
case DW_TAG_lexical_block:
dwarf2_parse_subprogram_block(ctx, child, func);
dwarf2_parse_subprogram_block(subpgm, block, child);
break;
case DW_TAG_subprogram:
/* FIXME: likely a declaration (to be checked)
* skip it for now
*/
break;
case DW_TAG_formal_parameter:
/* FIXME: likely elements for exception handling (GCC flavor)
* Skip it for now
*/
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
@ -1151,10 +1188,12 @@ static void dwarf2_parse_subprogram_block(dwarf2_parse_context_t* ctx,
break;
default:
FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
child->abbrev->tag, dwarf2_debug_ctx(ctx), dwarf2_debug_di(di));
child->abbrev->tag, dwarf2_debug_ctx(subpgm->ctx), dwarf2_debug_di(di));
}
}
}
symt_close_func_block(subpgm->ctx->module, subpgm->func, block, 0);
}
static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
@ -1166,9 +1205,10 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
union attribute high_pc;
union attribute is_decl;
union attribute inline_flags;
union attribute frame;
struct symt* ret_type;
struct symt_function* func = NULL;
struct symt_function_signature* sig_type;
dwarf2_subprogram_t subpgm;
if (di->symt) return di->symt;
@ -1185,12 +1225,27 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C);
if (!is_decl.uvalue)
{
func = symt_new_function(ctx->module, compiland, name.string,
ctx->module->module.BaseOfImage + low_pc.uvalue,
high_pc.uvalue - low_pc.uvalue,
&sig_type->symt);
di->symt = &func->symt;
subpgm.func = symt_new_function(ctx->module, compiland, name.string,
ctx->module->module.BaseOfImage + low_pc.uvalue,
high_pc.uvalue - low_pc.uvalue,
&sig_type->symt);
di->symt = &subpgm.func->symt;
}
else subpgm.func = NULL;
subpgm.ctx = ctx;
subpgm.compiland = compiland;
if (dwarf2_find_attribute(di, DW_AT_frame_base, &frame))
{
subpgm.frame_offset = dwarf2_compute_location(ctx, frame.block, &subpgm.frame_reg);
TRACE("For %s got %ld/%d\n", name.string, subpgm.frame_offset, subpgm.frame_reg);
}
else /* on stack !! */
{
subpgm.frame_reg = 0;
subpgm.frame_offset = 0;
}
if (di->abbrev->have_child) /** any interest to not have child ? */
{
dwarf2_debug_info_t** pchild = NULL;
@ -1202,17 +1257,15 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
switch (child->abbrev->tag)
{
case DW_TAG_variable:
case DW_TAG_formal_parameter:
dwarf2_parse_subprogram_parameter(ctx, func, NULL, child);
dwarf2_parse_variable(&subpgm, NULL, child);
break;
case DW_TAG_lexical_block:
dwarf2_parse_subprogram_block(ctx, child, func);
break;
case DW_TAG_variable:
dwarf2_parse_variable(ctx, child);
dwarf2_parse_subprogram_block(&subpgm, NULL, child);
break;
case DW_TAG_inlined_subroutine:
dwarf2_parse_inlined_subroutine(ctx, child);
dwarf2_parse_inlined_subroutine(&subpgm, child);
break;
case DW_TAG_subprogram:
/* FIXME: likely a declaration (to be checked)
@ -1220,7 +1273,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
*/
break;
case DW_TAG_label:
dwarf2_parse_subprogram_label(ctx, func, child);
dwarf2_parse_subprogram_label(&subpgm, child);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
@ -1239,7 +1292,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
}
}
symt_normalize_function(ctx->module, func);
symt_normalize_function(subpgm.ctx->module, subpgm.func);
return di->symt;
}