dbghelp: Fix conversion of dwarf's basic types into dbghelp's basic types.

Signed-off-by: Eric Pouech <eric.pouech@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Eric Pouech 2022-05-10 17:11:08 +02:00 committed by Alexandre Julliard
parent 14462bbeab
commit d94f4747e8
1 changed files with 56 additions and 4 deletions

View File

@ -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);