Eric Pouech : dbghelp: Fix conversion of dwarf's basic types into dbghelp's basic types.
Alexandre Julliard
julliard at winehq.org
Fri May 13 15:45:13 CDT 2022
Module: wine
Branch: master
Commit: d94f4747e877b87400d4cb0d11d1c09139ad2c87
URL: https://source.winehq.org/git/wine.git/?a=commit;h=d94f4747e877b87400d4cb0d11d1c09139ad2c87
Author: Eric Pouech <eric.pouech at gmail.com>
Date: Tue May 10 17:11:08 2022 +0200
dbghelp: Fix conversion of dwarf's basic types into dbghelp's basic types.
Signed-off-by: Eric Pouech <eric.pouech at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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);
More information about the wine-cvs
mailing list