From d94f4747e877b87400d4cb0d11d1c09139ad2c87 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Tue, 10 May 2022 17:11:08 +0200 Subject: [PATCH] dbghelp: Fix conversion of dwarf's basic types into dbghelp's basic types. Signed-off-by: Eric Pouech Signed-off-by: Alexandre Julliard --- dlls/dbghelp/dwarf.c | 60 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 19c0da933d3..5c0f34d4bf5 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -213,6 +213,7 @@ typedef struct dwarf2_parse_context_s dwarf2_cuhead_t head; enum unit_status status; dwarf2_traverse_context_t traverse_DIE; + unsigned language; } dwarf2_parse_context_t; /* stored in the dbghelp's module internal structure for later reuse */ @@ -1450,16 +1451,43 @@ static struct vector* dwarf2_get_di_children(dwarf2_debug_info_t* di) return NULL; } +/* reconstruct whether integer is long (contains 'long' only once) */ +static BOOL is_long(const char* name) +{ + /* we assume name is made only of basic C keywords: + * int long short unsigned signed void float double char _Bool _Complex + */ + const char* p = strstr(name, "long"); + return p && strstr(p + 4, "long") == NULL; +} + +static BOOL is_c_language(dwarf2_parse_context_t* unit_ctx) +{ + return unit_ctx->language == DW_LANG_C || + unit_ctx->language == DW_LANG_C89 || + unit_ctx->language == DW_LANG_C99; +} + +static BOOL is_cpp_language(dwarf2_parse_context_t* unit_ctx) +{ + return unit_ctx->language == DW_LANG_C_plus_plus; +} + static struct symt* dwarf2_parse_base_type(dwarf2_debug_info_t* di) { struct attribute name; struct attribute size; struct attribute encoding; enum BasicType bt; + BOOL c_language, cpp_language; + if (di->symt) return di->symt; TRACE("%s\n", dwarf2_debug_di(di)); + c_language = is_c_language(di->unit_ctx); + cpp_language = is_cpp_language(di->unit_ctx); + if (!dwarf2_find_attribute(di, DW_AT_name, &name)) name.u.string = NULL; if (!dwarf2_find_attribute(di, DW_AT_byte_size, &size)) size.u.uvalue = 0; @@ -1472,10 +1500,19 @@ static struct symt* dwarf2_parse_base_type(dwarf2_debug_info_t* di) case DW_ATE_boolean: bt = btBool; break; case DW_ATE_complex_float: bt = btComplex; break; case DW_ATE_float: bt = btFloat; break; - case DW_ATE_signed: bt = btInt; break; - case DW_ATE_unsigned: bt = btUInt; break; - case DW_ATE_signed_char: bt = btChar; break; - case DW_ATE_unsigned_char: bt = btChar; break; + case DW_ATE_signed: bt = ((c_language || cpp_language) && is_long(name.u.string)) ? btLong : btInt; break; + case DW_ATE_unsigned: + if ((c_language || cpp_language) && is_long(name.u.string)) bt = btULong; + else if (cpp_language && !strcmp(name.u.string, "wchar_t")) bt = btWChar; + else if (cpp_language && !strcmp(name.u.string, "char8_t")) bt = btChar8; + else if (cpp_language && !strcmp(name.u.string, "char16_t")) bt = btChar16; + else if (cpp_language && !strcmp(name.u.string, "char32_t")) bt = btChar32; + else bt = btUInt; + break; + /* on Windows, in C, char == signed char, but not in C++ */ + case DW_ATE_signed_char: bt = (cpp_language && !strcmp(name.u.string, "signed char")) ? btInt : btChar; break; + case DW_ATE_unsigned_char: bt = btUInt; break; + case DW_ATE_UTF: bt = (size.u.uvalue == 1) ? btChar8 : (size.u.uvalue == 2 ? btChar16 : btChar32); break; default: bt = btNoType; break; } di->symt = &symt_get_basic(bt, size.u.uvalue)->symt; @@ -1497,7 +1534,15 @@ static struct symt* dwarf2_parse_typedef(dwarf2_debug_info_t* di) ref_type = dwarf2_lookup_type(di); if (name.u.string) + { + /* Note: The MS C compiler has tweaks for WCHAR support. + * Even if WCHAR is a typedef to wchar_t, wchar_t is emitted as btUInt/2 (it's defined as + * unsigned short, so far so good), while WCHAR is emitted as btWChar/2). + */ + if ((is_c_language(di->unit_ctx) || is_cpp_language(di->unit_ctx)) && !strcmp(name.u.string, "WCHAR")) + ref_type = &symt_get_basic(btWChar, 2)->symt; di->symt = &symt_new_typedef(di->unit_ctx->module_ctx->module, ref_type, name.u.string)->symt; + } if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); return di->symt; } @@ -2917,6 +2962,7 @@ static BOOL dwarf2_parse_compilation_unit(dwarf2_parse_context_t* ctx) unsigned int i; struct attribute stmt_list, low_pc; struct attribute comp_dir; + struct attribute language; if (!dwarf2_find_attribute(di, DW_AT_name, &name)) name.u.string = NULL; @@ -2927,6 +2973,12 @@ static BOOL dwarf2_parse_compilation_unit(dwarf2_parse_context_t* ctx) if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc)) low_pc.u.uvalue = 0; + + if (!dwarf2_find_attribute(di, DW_AT_language, &language)) + language.u.uvalue = DW_LANG_C; + + ctx->language = language.u.uvalue; + ctx->compiland = symt_new_compiland(ctx->module_ctx->module, ctx->module_ctx->load_offset + low_pc.u.uvalue, source_new(ctx->module_ctx->module, comp_dir.u.string, name.u.string)); dwarf2_cache_cuhead(ctx->module_ctx->module->format_info[DFI_DWARF]->u.dwarf2_info, ctx->compiland, &ctx->head);