This serie (PDB rewrite #3) mostly handles the debug information needed to support C++ enum underlying integral type. - it generalizes the use of VARIANT to gather enum values, - to make things simple, in PDB, the type of variant used has nothing to do with the size of the C++ integral type, but is the smallest size to hold the considered enum value, - adapt the dwarf backend to behave the same way as the PDB one, - adapt debugger to support up to 8-bytes variant types.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/winedbg/memory.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 5431c4297cd..3da70e1bfb2 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -601,14 +601,18 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) for (i = 0; i < min(fcp->Count, count); i++) { sub_type.id = fcp->ChildId[i]; - if (!types_get_info(&sub_type, TI_GET_VALUE, &variant)) + if (!types_get_info(&sub_type, TI_GET_VALUE, &variant)) continue; switch (V_VT(&variant)) { - case VT_I1: ok = (val_int == V_I1(&variant)); break; - case VT_I2: ok = (val_int == V_I2(&variant)); break; - case VT_I4: ok = (val_int == V_I4(&variant)); break; - case VT_I8: ok = (val_int == V_I8(&variant)); break; + case VT_I1: ok = (val_int == V_I1(&variant)); break; + case VT_I2: ok = (val_int == V_I2(&variant)); break; + case VT_I4: ok = (val_int == V_I4(&variant)); break; + case VT_I8: ok = (val_int == V_I8(&variant)); break; + case VT_UI1: ok = (val_int == (dbg_lguint_t)V_UI1(&variant)); break; + case VT_UI2: ok = (val_int == (dbg_lguint_t)V_UI2(&variant)); break; + case VT_UI4: ok = (val_int == (dbg_lguint_t)V_UI4(&variant)); break; + case VT_UI8: ok = (val_int == (dbg_lguint_t)V_UI8(&variant)); break; default: WINE_FIXME("Unsupported variant type (%u)\n", V_VT(&variant)); } if (ok && types_get_info(&sub_type, TI_GET_SYMNAME, &ptr) && ptr)
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 6 +++--- dlls/dbghelp/dwarf.c | 6 +++++- dlls/dbghelp/msc.c | 10 ++++++++-- dlls/dbghelp/stabs.c | 7 +++++-- dlls/dbghelp/type.c | 5 ++--- 5 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 2d7d84f017e..5979eb7955a 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -930,9 +930,9 @@ extern BOOL symt_add_udt_element(struct module* module, extern struct symt_enum* symt_new_enum(struct module* module, const char* typename, struct symt* basetype); -extern BOOL symt_add_enum_element(struct module* module, - struct symt_enum* enum_type, - const char* name, int value); +extern BOOL symt_add_enum_element(struct module* module, + struct symt_enum* enum_type, + const char* name, const VARIANT *value); extern struct symt_array* symt_new_array(struct module* module, int min, DWORD count, struct symt* base, struct symt* index); diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 10549a11579..e15242f01a8 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1838,6 +1838,7 @@ static struct symt* dwarf2_parse_udt_type(dwarf2_debug_info_t* di, static void dwarf2_parse_enumerator(dwarf2_debug_info_t* di, struct symt_enum* parent) { + VARIANT v; struct attribute name; struct attribute value;
@@ -1845,7 +1846,10 @@ static void dwarf2_parse_enumerator(dwarf2_debug_info_t* di,
if (!dwarf2_find_attribute(di, DW_AT_name, &name)) return; if (!dwarf2_find_attribute(di, DW_AT_const_value, &value)) value.u.svalue = 0; - symt_add_enum_element(di->unit_ctx->module_ctx->module, parent, name.u.string, value.u.svalue); + V_VT(&v) = VT_I4; + V_I4(&v) = value.u.svalue; + + symt_add_enum_element(di->unit_ctx->module_ctx->module, parent, name.u.string, &v);
if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); } diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 51025242879..18080768fad 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -891,19 +891,25 @@ static BOOL codeview_add_type_enum_field_list(struct codeview_type_parse* ctp, { case LF_ENUMERATE_V1: { + VARIANT v; int value, vlen = numeric_leaf(&value, type->enumerate_v1.data); const struct p_string* p_name = (const struct p_string*)&type->enumerate_v1.data[vlen]; + V_VT(&v) = VT_I4; + V_I4(&v) = value;
- symt_add_enum_element(ctp->module, symt, terminate_string(p_name), value); + symt_add_enum_element(ctp->module, symt, terminate_string(p_name), &v); ptr += 2 + 2 + vlen + (1 + p_name->namelen); break; } case LF_ENUMERATE_V3: { + VARIANT v; int value, vlen = numeric_leaf(&value, type->enumerate_v3.data); const char* name = (const char*)&type->enumerate_v3.data[vlen]; + V_VT(&v) = VT_I4; + V_I4(&v) = value;
- symt_add_enum_element(ctp->module, symt, name, value); + symt_add_enum_element(ctp->module, symt, name, &v); ptr += 2 + 2 + vlen + (1 + strlen(name)); break; } diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index 2f3ee9fff4e..d02f320e281 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -718,9 +718,10 @@ static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd, return 0; }
-static inline int stabs_pts_read_enum(struct ParseTypedefData* ptd, +static inline int stabs_pts_read_enum(struct ParseTypedefData* ptd, struct symt_enum* edt) { + VARIANT v; LONG_PTR value; int idx;
@@ -730,7 +731,9 @@ static inline int stabs_pts_read_enum(struct ParseTypedefData* ptd, PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1); PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &value) == -1); PTS_ABORTIF(ptd, *ptd->ptr++ != ','); - symt_add_enum_element(ptd->module, edt, ptd->buf + idx, value); + V_VT(&v) = VT_I4; + V_I4(&v) = value; + symt_add_enum_element(ptd->module, edt, ptd->buf + idx, &v); ptd->idx = idx; } ptd->ptr++; diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index 7e9bb44e690..a3ad80aacbb 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -342,7 +342,7 @@ struct symt_enum* symt_new_enum(struct module* module, const char* typename, }
BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type, - const char* name, int value) + const char* name, const VARIANT *variant) { struct symt_data* e; struct symt** p; @@ -357,8 +357,7 @@ BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type, e->kind = DataIsConstant; e->container = &enum_type->symt; e->type = enum_type->base_type; - V_VT(&e->u.value) = VT_I4; - V_I4(&e->u.value) = value; + e->u.value = *variant;
p = vector_add(&enum_type->vchildren, &module->pool); if (!p) return FALSE; /* FIXME we leak e */
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 18080768fad..f5872442263 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -273,15 +273,15 @@ static int leaf_as_variant(VARIANT *v, const unsigned char *leaf) { unsigned short int type = *(const unsigned short *)leaf; int length = 2; - leaf += length;
if (type < LF_NUMERIC) { - V_VT(v) = VT_UINT; - V_UINT(v) = type; + V_VT(v) = VT_I2; + V_I2(v) = type; } else { + leaf += length; switch (type) { case LF_CHAR: @@ -892,10 +892,8 @@ static BOOL codeview_add_type_enum_field_list(struct codeview_type_parse* ctp, case LF_ENUMERATE_V1: { VARIANT v; - int value, vlen = numeric_leaf(&value, type->enumerate_v1.data); + int vlen = leaf_as_variant(&v, type->enumerate_v1.data); const struct p_string* p_name = (const struct p_string*)&type->enumerate_v1.data[vlen]; - V_VT(&v) = VT_I4; - V_I4(&v) = value;
symt_add_enum_element(ctp->module, symt, terminate_string(p_name), &v); ptr += 2 + 2 + vlen + (1 + p_name->namelen); @@ -904,10 +902,8 @@ static BOOL codeview_add_type_enum_field_list(struct codeview_type_parse* ctp, case LF_ENUMERATE_V3: { VARIANT v; - int value, vlen = numeric_leaf(&value, type->enumerate_v3.data); + int vlen = leaf_as_variant(&v, type->enumerate_v3.data); const char* name = (const char*)&type->enumerate_v3.data[vlen]; - V_VT(&v) = VT_I4; - V_I4(&v) = value;
symt_add_enum_element(ctp->module, symt, name, &v); ptr += 2 + 2 + vlen + (1 + strlen(name));
From: Eric Pouech epouech@codeweavers.com
As they can represent constant values, use largest possible integral type.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dwarf.c | 70 ++++++++++++++++++++++++++------------------ dlls/dbghelp/msc.c | 7 +++-- 2 files changed, 46 insertions(+), 31 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index e15242f01a8..630c439f240 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -128,6 +128,7 @@ struct attribute ULONG_PTR uvalue; ULONGLONG lluvalue; LONG_PTR svalue; + LONGLONG llsvalue; const char* string; struct dwarf2_block block; } u; @@ -282,18 +283,19 @@ static DWORD64 dwarf2_parse_u8(dwarf2_traverse_context_t* ctx) return uvalue; }
-static ULONG_PTR dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end) +static ULONG64 dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end) { - ULONG_PTR ret = 0; + ULONG64 ret = 0; unsigned char byte; unsigned shift = 0;
do { byte = dwarf2_get_byte(ptr++); - ret |= (byte & 0x7f) << shift; + ret |= (ULONG64)(byte & 0x7f) << shift; shift += 7; } while (byte & 0x80); + if ((ret >> (shift - 7)) != (byte & 0x7F)) FIXME("Overflow in LEB128 encoding\n");
if (end) *end = ptr; return ret; @@ -301,47 +303,45 @@ static ULONG_PTR dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const u
static ULONG_PTR dwarf2_leb128_as_unsigned(dwarf2_traverse_context_t* ctx) { - ULONG_PTR ret; + ULONG64 ret;
assert(ctx);
ret = dwarf2_get_leb128_as_unsigned(ctx->data, &ctx->data); - + if (ret != (ULONG_PTR)ret) WARN("Dropping bits from LEB128 value\n"); return ret; }
-static LONG_PTR dwarf2_get_leb128_as_signed(const unsigned char* ptr, const unsigned char** end) +static LONG64 dwarf2_get_leb128_as_signed(const unsigned char* ptr, const unsigned char** end) { - LONG_PTR ret = 0; + ULONG64 ret = 0; unsigned char byte; unsigned shift = 0; - const unsigned size = sizeof(int) * 8;
do { byte = dwarf2_get_byte(ptr++); - ret |= (byte & 0x7f) << shift; + ret |= (ULONG64)(byte & 0x7f) << shift; shift += 7; } while (byte & 0x80); - if (end) *end = ptr;
- /* as spec: sign bit of byte is 2nd high order bit (80x40) - * -> 0x80 is used as flag. - */ - if ((shift < size) && (byte & 0x40)) - { - ret |= - (1 << shift); - } + if (end) *end = ptr; + if ((shift < sizeof(ULONG64) * 8) && (byte & 0x40)) + /* as spec: sign bit of byte is 2nd high order bit (80x40) + * -> 0x80 is used as flag. + */ + ret |= ~(ULONG64)0 << shift; return ret; }
static LONG_PTR dwarf2_leb128_as_signed(dwarf2_traverse_context_t* ctx) { - LONG_PTR ret = 0; + LONG64 ret = 0;
assert(ctx);
ret = dwarf2_get_leb128_as_signed(ctx->data, &ctx->data); + if (ret != (LONG_PTR)ret) WARN("Dropping bits from LEB128 value\n"); return ret; }
@@ -609,16 +609,16 @@ static BOOL dwarf2_fill_attr(const dwarf2_parse_context_t* ctx, break;
case DW_FORM_sdata: - attr->u.svalue = dwarf2_get_leb128_as_signed(data, NULL); + attr->u.llsvalue = dwarf2_get_leb128_as_signed(data, NULL); break;
case DW_FORM_ref_udata: - attr->u.uvalue = ctx->ref_offset + dwarf2_get_leb128_as_unsigned(data, NULL); + attr->u.lluvalue = ctx->ref_offset + dwarf2_get_leb128_as_unsigned(data, NULL); TRACE("ref_udata<0x%Ix>\n", attr->u.uvalue); break;
case DW_FORM_udata: - attr->u.uvalue = dwarf2_get_leb128_as_unsigned(data, NULL); + attr->u.lluvalue = dwarf2_get_leb128_as_unsigned(data, NULL); TRACE("udata<0x%Ix>\n", attr->u.uvalue); break;
@@ -1061,12 +1061,24 @@ static BOOL dwarf2_compute_location_attr(dwarf2_parse_context_t* ctx, return TRUE; } /* fall through */ - case DW_FORM_data1: case DW_FORM_data2: - case DW_FORM_udata: case DW_FORM_sdata: + case DW_FORM_data1: + case DW_FORM_data2: + loc->kind = loc_absolute; + loc->reg = 0; + loc->offset = xloc.u.uvalue; + return TRUE; + case DW_FORM_udata: loc->kind = loc_absolute; loc->reg = 0; + if (xloc.u.uvalue != xloc.u.lluvalue) WARN("Cropping integral value\n"); loc->offset = xloc.u.uvalue; return TRUE; + case DW_FORM_sdata: + loc->kind = loc_absolute; + loc->reg = 0; + if (xloc.u.svalue != xloc.u.llsvalue) WARN("Cropping integral value\n"); + loc->offset = xloc.u.svalue; + return TRUE; case DW_FORM_data8: if (ctx->head.version >= 4) { @@ -1285,12 +1297,14 @@ static BOOL dwarf2_fill_ranges(const dwarf2_debug_info_t* di, struct addr_range* { case DW_FORM_addr: break; + case DW_FORM_sdata: + case DW_FORM_udata: + if (high_pc.u.uvalue != high_pc.u.lluvalue) WARN("Cropping integral value\n"); + /* fall through */ case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: - case DW_FORM_sdata: - case DW_FORM_udata: /* From dwarf4 on, when FORM's class is constant, high_pc is an offset from low_pc */ high_pc.u.uvalue += low_pc.u.uvalue; break; @@ -1999,12 +2013,12 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm, case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: - case DW_FORM_udata: case DW_FORM_addr: V_VT(&v) = VT_UI4; V_UI4(&v) = value.u.uvalue; break;
+ case DW_FORM_udata: case DW_FORM_data8: case DW_FORM_sec_offset: V_VT(&v) = VT_UI8; @@ -2012,8 +2026,8 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm, break;
case DW_FORM_sdata: - V_VT(&v) = VT_I4; - V_I4(&v) = value.u.svalue; + V_VT(&v) = VT_I8; + V_I8(&v) = value.u.llsvalue; break;
case DW_FORM_strp: diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index f5872442263..c01a8fd9c69 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -395,7 +395,8 @@ static int leaf_as_variant(VARIANT *v, const unsigned char *leaf) return length; }
-static int numeric_leaf(int *value, const unsigned char *leaf) +#define numeric_leaf(v,l) _numeric_leaf(__LINE__,v,l) +static int _numeric_leaf(unsigned line, int *value, const unsigned char *leaf) { unsigned short int type = *(const unsigned short int *)leaf; int length = 2; @@ -436,7 +437,7 @@ static int numeric_leaf(int *value, const unsigned char *leaf)
case LF_QUADWORD: case LF_UQUADWORD: - FIXME("Unsupported numeric leaf type %04x\n", type); + FIXME("Unsupported numeric leaf type %04x from %u (%I64x)\n", type, line, *(ULONG64*)leaf); length += 8; *value = 0; /* FIXME */ break; @@ -2786,7 +2787,7 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, if (top_frame_size == -1 && curr_func && curr_func == top_func) top_frame_size = sym->frame_info_v2.sz_frame; else - FIXME("Unexpected S_FRAMEPROC %d (%p %p)\n", top_frame_size, top_func, curr_func); + FIXME("Unexpected S_FRAMEPROC %d (%p %p) %x\n", top_frame_size, top_func, curr_func, i); break;
/* the symbols we can safely ignore for now */
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dwarf.c | 110 +++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 52 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 630c439f240..7c4ad1dd065 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -712,6 +712,63 @@ static BOOL dwarf2_fill_attr(const dwarf2_parse_context_t* ctx, return TRUE; }
+static BOOL dwarf2_fill_in_variant(struct module *module, VARIANT *v, const struct attribute *attr) +{ + switch (attr->form) + { + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_addr: + V_VT(v) = VT_UI4; + V_UI4(v) = attr->u.uvalue; + break; + + case DW_FORM_udata: + case DW_FORM_data8: + case DW_FORM_sec_offset: + V_VT(v) = VT_UI8; + V_UI8(v) = attr->u.lluvalue; + break; + + case DW_FORM_sdata: + V_VT(v) = VT_I8; + V_I8(v) = attr->u.llsvalue; + break; + + case DW_FORM_strp: + case DW_FORM_string: + /* FIXME: native doesn't report const strings from here !! + * however, the value of the string is in the code somewhere + */ + V_VT(v) = VT_BYREF; + V_BYREF(v) = pool_strdup(&module->pool, attr->u.string); + break; + + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_exprloc: + V_VT(v) = VT_I4; + switch (attr->u.block.size) + { + case 1: V_I4(v) = *(BYTE*)attr->u.block.ptr; break; + case 2: V_I4(v) = *(USHORT*)attr->u.block.ptr; break; + case 4: V_I4(v) = *(DWORD*)attr->u.block.ptr; break; + default: + V_VT(v) = VT_BYREF; + V_BYREF(v) = pool_alloc(&module->pool, attr->u.block.size); + memcpy(V_BYREF(v), attr->u.block.ptr, attr->u.block.size); + } + break; + default: + V_VT(v) = VT_EMPTY; + return FALSE; + } + return TRUE; +} + static dwarf2_debug_info_t* dwarf2_jump_to_debug_info(struct attribute* attr);
static BOOL dwarf2_find_attribute(const dwarf2_debug_info_t* di, @@ -2008,60 +2065,9 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm, { VARIANT v;
- switch (value.form) - { - case DW_FORM_data1: - case DW_FORM_data2: - case DW_FORM_data4: - case DW_FORM_addr: - V_VT(&v) = VT_UI4; - V_UI4(&v) = value.u.uvalue; - break; - - case DW_FORM_udata: - case DW_FORM_data8: - case DW_FORM_sec_offset: - V_VT(&v) = VT_UI8; - V_UI8(&v) = value.u.lluvalue; - break; - - case DW_FORM_sdata: - V_VT(&v) = VT_I8; - V_I8(&v) = value.u.llsvalue; - break; - - case DW_FORM_strp: - case DW_FORM_string: - /* FIXME: native doesn't report const strings from here !! - * however, the value of the string is in the code somewhere - */ - V_VT(&v) = VT_BYREF; - V_BYREF(&v) = pool_strdup(&subpgm->ctx->module_ctx->module->pool, value.u.string); - break; - - case DW_FORM_block: - case DW_FORM_block1: - case DW_FORM_block2: - case DW_FORM_block4: - case DW_FORM_exprloc: - V_VT(&v) = VT_I4; - switch (value.u.block.size) - { - case 1: V_I4(&v) = *(BYTE*)value.u.block.ptr; break; - case 2: V_I4(&v) = *(USHORT*)value.u.block.ptr; break; - case 4: V_I4(&v) = *(DWORD*)value.u.block.ptr; break; - default: - V_VT(&v) = VT_BYREF; - V_BYREF(&v) = pool_alloc(&subpgm->ctx->module_ctx->module->pool, value.u.block.size); - memcpy(V_BYREF(&v), value.u.block.ptr, value.u.block.size); - } - break; - - default: + if (!dwarf2_fill_in_variant(subpgm->ctx->module_ctx->module, &v, &value)) FIXME("Unsupported form for const value %s (%Ix)\n", debugstr_a(name.u.string), value.form); - V_VT(&v) = VT_EMPTY; - } if (subpgm->current_func) { if (is_pmt) WARN("Constant parameter %s reported as local variable in function '%s'\n",
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dwarf.c | 121 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 19 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 7c4ad1dd065..883b04dd6a1 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -712,28 +712,48 @@ static BOOL dwarf2_fill_attr(const dwarf2_parse_context_t* ctx, return TRUE; }
-static BOOL dwarf2_fill_in_variant(struct module *module, VARIANT *v, const struct attribute *attr) +static struct symt *symt_get_real_type(struct symt *symt) { + while (symt && symt->tag == SymTagTypedef) + symt = ((struct symt_typedef*)symt)->type; + return symt; +} + +static BOOL dwarf2_fill_in_variant(struct module *module, VARIANT *v, const struct attribute *attr, struct symt *type) +{ + ULONG64 uinteger; + LONG64 sinteger; + enum BasicType bt = btInt; + + type = symt_get_real_type(type); + if (symt_check_tag(type, SymTagBaseType)) + bt = ((struct symt_basic*)type)->bt; + + /* data1, data2, data4 can hold either signed or unsigned values... + * so ensure proper extension of signed types... + */ switch (attr->form) { case DW_FORM_data1: + uinteger = attr->u.uvalue; + sinteger = (char)(unsigned char)attr->u.uvalue; + break; case DW_FORM_data2: + uinteger = attr->u.uvalue; + sinteger = (short)(unsigned short)attr->u.uvalue; + break; case DW_FORM_data4: - case DW_FORM_addr: - V_VT(v) = VT_UI4; - V_UI4(v) = attr->u.uvalue; + uinteger = attr->u.uvalue; + sinteger = (int)(unsigned int)attr->u.uvalue; break;
case DW_FORM_udata: case DW_FORM_data8: - case DW_FORM_sec_offset: - V_VT(v) = VT_UI8; - V_UI8(v) = attr->u.lluvalue; + sinteger = uinteger = attr->u.lluvalue; break;
case DW_FORM_sdata: - V_VT(v) = VT_I8; - V_I8(v) = attr->u.llsvalue; + uinteger = sinteger = attr->u.llsvalue; break;
case DW_FORM_strp: @@ -743,6 +763,7 @@ static BOOL dwarf2_fill_in_variant(struct module *module, VARIANT *v, const stru */ V_VT(v) = VT_BYREF; V_BYREF(v) = pool_strdup(&module->pool, attr->u.string); + return TRUE; break;
case DW_FORM_block: @@ -761,11 +782,68 @@ static BOOL dwarf2_fill_in_variant(struct module *module, VARIANT *v, const stru V_BYREF(v) = pool_alloc(&module->pool, attr->u.block.size); memcpy(V_BYREF(v), attr->u.block.ptr, attr->u.block.size); } + return TRUE; break; + case DW_FORM_sec_offset: + case DW_FORM_addr: + FIXME("Unexpected form %Ix\n", attr->form); default: V_VT(v) = VT_EMPTY; return FALSE; } + /* native always stores in the shortest format in variant */ + if (bt == btChar || bt == btInt || bt == btLong) + { + if (sinteger == (signed char)sinteger) + { + V_VT(v) = VT_I1; + V_I1(v) = sinteger; + } + if (sinteger == (short int)sinteger) + { + V_VT(v) = VT_I2; + V_I2(v) = sinteger; + } + else if (sinteger == (int)sinteger) + { + V_VT(v) = VT_I4; + V_I4(v) = sinteger; + } + else + { + V_VT(v) = VT_I8; + V_I8(v) = sinteger; + } + } + else if (bt == btUInt || bt == btULong || bt == btWChar) + { + if (uinteger == (unsigned char)uinteger) + { + V_VT(v) = VT_UI1; + V_UI1(v) = uinteger; + } + else if (uinteger == (unsigned short int)uinteger) + { + V_VT(v) = VT_UI2; + V_UI2(v) = uinteger; + } + else if (uinteger == (unsigned int)uinteger) + { + V_VT(v) = VT_UI4; + V_UI4(v) = uinteger; + } + else + { + V_VT(v) = VT_UI8; + V_UI8(v) = uinteger; + } + } + else + { + FIXME("Unexpected base type bt=%x for form=%Ix\n", bt, attr->form); + return FALSE; + } + return TRUE; }
@@ -1915,11 +1993,15 @@ static void dwarf2_parse_enumerator(dwarf2_debug_info_t* di,
TRACE("%s\n", dwarf2_debug_di(di));
- if (!dwarf2_find_attribute(di, DW_AT_name, &name)) return; - if (!dwarf2_find_attribute(di, DW_AT_const_value, &value)) value.u.svalue = 0; - V_VT(&v) = VT_I4; - V_I4(&v) = value.u.svalue; + V_VT(&v) = VT_EMPTY;
+ if (!dwarf2_find_attribute(di, DW_AT_name, &name)) return; + if (dwarf2_find_attribute(di, DW_AT_const_value, &value) && + symt_check_tag(parent->base_type, SymTagBaseType)) + { + if (!dwarf2_fill_in_variant(di->unit_ctx->module_ctx->module, &v, &value, parent->base_type)) + TRACE("Failed to get variant\n"); + } symt_add_enum_element(di->unit_ctx->module_ctx->module, parent, name.u.string, &v);
if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); @@ -1930,7 +2012,7 @@ static struct symt* dwarf2_parse_enumeration_type(dwarf2_debug_info_t* di) struct attribute name; struct attribute attrtype; dwarf2_debug_info_t*ditype; - struct symt* type; + struct symt* type = NULL; struct vector* children; dwarf2_debug_info_t*child; unsigned int i; @@ -1941,20 +2023,20 @@ static struct symt* dwarf2_parse_enumeration_type(dwarf2_debug_info_t* di)
if (!dwarf2_find_attribute(di, DW_AT_name, &name)) name.u.string = NULL; if (dwarf2_find_attribute(di, DW_AT_type, &attrtype) && (ditype = dwarf2_jump_to_debug_info(&attrtype)) != NULL) - type = ditype->symt; - else /* no type found for this enumeration, construct it from size */ + type = symt_get_real_type(ditype->symt); + if (!type || type->tag != SymTagBaseType) /* no type found for this enumeration, construct it from size */ { struct attribute size; struct symt_basic* basetype;
if (!dwarf2_find_attribute(di, DW_AT_byte_size, &size)) size.u.uvalue = 4; - - switch (size.u.uvalue) /* FIXME: that's wrong */ + switch (size.u.uvalue) { case 1: basetype = symt_get_basic(btInt, 1); break; case 2: basetype = symt_get_basic(btInt, 2); break; default: case 4: basetype = symt_get_basic(btInt, 4); break; + case 8: basetype = symt_get_basic(btInt, 8); break; } type = &basetype->symt; } @@ -2065,9 +2147,10 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm, { VARIANT v;
- if (!dwarf2_fill_in_variant(subpgm->ctx->module_ctx->module, &v, &value)) + if (!dwarf2_fill_in_variant(subpgm->ctx->module_ctx->module, &v, &value, param_type)) FIXME("Unsupported form for const value %s (%Ix)\n", debugstr_a(name.u.string), value.form); + if (subpgm->current_func) { if (is_pmt) WARN("Constant parameter %s reported as local variable in function '%s'\n",