Wine's dbghelp's implementation differ from native regarding basic types' handling (the basic types like char, int, long...) - Wine's dbghelp exposes a name for such a type, while native doesn't - parsing of basic type from dwarf & pdb don't always exactly return the correct information. Two examples (among others) of discrepancies: - in C, under Windows assumption, char, signed char and unsigned char are mapped to 2 types (as char = signed char); while in C++, they are mapped to three different types (char and signed char are two different types). Wine's dbhelp doesn't report correctly the C++ char types, and the char/signed char is broken too. - MS compiler shamelessly maps WCHAR to btWChar (basic type), while it's a typedef to unsigned short (which is mapped to btInt of size 2)
This series's result is that Wine dbghelp's now returns the same basic types as native. (Tested with most of the C & C++ basic types)
This requires: - to implement the re-generation of the basic types' name in WineDbg. This is done by adding data model tables (ILP32, LP64 and LLP64), and picking up the right one depending on current executable. Option is also added in WineDbg to force a(nother) data model. This is only used when printing types, not when reading/writing integer values as this (mostly) relies on the size of the integer. - fixing the pdb and dwarf backends in dbghelp to retarget the correct base types (for C and C++ basic types) - removing the name field from dbghelp's struct symt_basic allowed some simplification inside dbghelp: + all basic types are now only allocated once across every compilation unit and module) (small speed and memory consumption gain) + dwarf's backend used a basic type cache which is also removed
Note: when using a basic type in WineDbg (like casting an integral value to another integral value), this serie doesn't change the data model used for getting the type's size.
The data model used is currently ILP32 on 32 bit, and always LP64 on 64 bit. Yet to come serie shall use the current data model instead.
From: Eric Pouech eric.pouech@gmail.com
added ILP32, LP64 and LLP64 data models
detect data model to be used with current debuggee PE & ELF 32 bit => ILP32 PE 64 bit => LP64 ELF 64 bit => LLP64
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- programs/winedbg/debugger.h | 7 ++ programs/winedbg/types.c | 176 +++++++++++++++++++++++++++++------- 2 files changed, 150 insertions(+), 33 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 293de4c0aa5..de6c8b3e438 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -544,6 +544,13 @@ static inline void* dbg_heap_realloc(void* buffer, size_t size) HeapAlloc(GetProcessHeap(), 0, size); }
+struct data_model +{ + unsigned base_type; + unsigned size; + const WCHAR* name; +}; + extern struct dbg_internal_var dbg_internal_vars[];
#define DBG_IVARNAME(_var) dbg_internal_var_##_var diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 50d1f1b8353..f4ee5a011d5 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -714,47 +714,157 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) return TRUE; }
+static const struct data_model ilp32_data_model[] = { + {btVoid, 0, L"void"}, + {btChar, 1, L"char"}, + {btWChar, 2, L"wchar_t"}, + {btInt, 1, L"signed char"}, + {btInt, 2, L"short int"}, + {btInt, 4, L"int"}, + {btInt, 8, L"__int64"}, + {btUInt, 1, L"unsigned char"}, + {btUInt, 2, L"unsigned short int"}, + {btUInt, 4, L"unsigned int"}, + {btUInt, 8, L"unsigned __int64"}, + {btFloat, 4, L"float"}, + {btFloat, 8, L"double"}, + {btFloat, 10, L"long double"}, + {btBool, 1, L"bool"}, + {btLong, 4, L"long"}, + {btLong, 8, L"long long"}, + {btULong, 4, L"unsigned long"}, + {btULong, 8, L"unsigned long long"}, + {btHresult, 4, L"char32_t"}, + {btChar16, 2, L"char16_t"}, + {btChar32, 4, L"char32_t"}, + {btChar8, 1, L"char8_t"}, + {0, 0, NULL} +}; + +static const struct data_model llp64_data_model[] = { + {btVoid, 0, L"void"}, + {btChar, 1, L"char"}, + {btWChar, 2, L"wchar_t"}, + {btInt, 1, L"signed char"}, + {btInt, 2, L"short int"}, + {btInt, 4, L"int"}, + {btInt, 8, L"__int64"}, + {btInt, 16, L"__int128"}, + {btUInt, 1, L"unsigned char"}, + {btUInt, 2, L"unsigned short int"}, + {btUInt, 4, L"unsigned int"}, + {btUInt, 8, L"unsigned __int64"}, + {btUInt, 16, L"unsigned __int128"}, + {btFloat, 4, L"float"}, + {btFloat, 8, L"double"}, + {btFloat, 10, L"long double"}, + {btBool, 1, L"bool"}, + {btLong, 4, L"long"}, + {btLong, 8, L"long long"}, + {btULong, 4, L"unsigned long"}, + {btULong, 8, L"unsigned long long"}, + {btHresult, 4, L"char32_t"}, + {btChar16, 2, L"char16_t"}, + {btChar32, 4, L"char32_t"}, + {btChar8, 1, L"char8_t"}, + {0, 0, NULL} +}; + +static const struct data_model lp64_data_model[] = { + {btVoid, 0, L"void"}, + {btChar, 1, L"char"}, + {btWChar, 2, L"wchar_t"}, + {btInt, 1, L"signed char"}, + {btInt, 2, L"short int"}, + {btInt, 4, L"int"}, + {btInt, 8, L"__int64"}, + {btInt, 16, L"__int128"}, + {btUInt, 1, L"unsigned char"}, + {btUInt, 2, L"unsigned short int"}, + {btUInt, 4, L"unsigned int"}, + {btUInt, 8, L"unsigned __int64"}, + {btUInt, 16, L"unsigned __int128"}, + {btFloat, 4, L"float"}, + {btFloat, 8, L"double"}, + {btFloat, 10, L"long double"}, + {btBool, 1, L"bool"}, + {btLong, 4, L"int"}, /* to print at least for such a regular Windows' type */ + {btLong, 8, L"long"}, /* we can't discriminate 'long' from 'long long' */ + {btULong, 4, L"unsigned int"}, /* to print at least for such a regular Windows' type */ + {btULong, 8, L"unsigned long"}, /* we can't discriminate 'unsigned long' from 'unsigned long long' */ + {btHresult, 4, L"char32_t"}, + {btChar16, 2, L"char16_t"}, + {btChar32, 4, L"char32_t"}, + {btChar8, 1, L"char8_t"}, + {0, 0, NULL} +}; + +static const struct data_model* get_data_model(DWORD modaddr) +{ + const struct data_model *model; + + if (ADDRSIZE == 4) model = ilp32_data_model; + else + { + IMAGEHLP_MODULEW64 mi; + DWORD opt = SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, TRUE); + + mi.SizeOfStruct = sizeof(mi); + if (SymGetModuleInfoW64(dbg_curr_process->handle, modaddr, &mi) && + (wcsstr(mi.ModuleName, L".so") || wcsstr(mi.ModuleName, L"<"))) + model = lp64_data_model; + else + model = llp64_data_model; + SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt); + } + return model; +} + /* helper to typecast pInfo to its expected type (_t) */ #define X(_t) (*((_t*)pInfo))
-BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo) +static BOOL lookup_base_type_in_data_model(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo) { - if (type->id == dbg_itype_none) return FALSE; - if (type->module != 0) + DWORD tag, bt; + DWORD64 len; + const WCHAR* name = NULL; + WCHAR tmp[64]; + const struct data_model* model; + + if (ti != TI_GET_SYMNAME || + !SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_SYMTAG, &tag) || + tag != SymTagBaseType || + !SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_BASETYPE, &bt) || + !SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_LENGTH, &len) || + len != (DWORD)len) return FALSE; + + model = get_data_model(type->module); + for (; model->name; model++) { - DWORD ret, tag, bt; - ret = SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo); - if (!ret && - ti == TI_GET_SYMNAME && - SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_SYMTAG, &tag) && - tag == SymTagBaseType && - SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, TI_GET_BASETYPE, &bt)) + if (bt == model->base_type && model->size == len) { - const WCHAR* name = NULL; - - switch (bt) - { - case btVoid: name = L"void"; break; - case btChar: name = L"char"; break; - case btWChar: name = L"WCHAR"; break; - case btInt: name = L"int"; break; - case btUInt: name = L"unsigned int"; break; - case btFloat: name = L"float"; break; - case btBool: name = L"bool"; break; - case btLong: name = L"long int"; break; - case btULong: name = L"unsigned long int"; break; - case btComplex: name = L"complex"; break; - default: WINE_FIXME("Unsupported basic type %lu\n", bt); return FALSE; - } - X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR)); - if (X(WCHAR*)) - { - lstrcpyW(X(WCHAR*), name); - ret = TRUE; - } + name = model->name; + break; } - return ret; } + if (!name) /* synthetize name */ + { + WINE_FIXME("Unsupported basic type %lu %I64u\n", bt, len); + swprintf(tmp, ARRAY_SIZE(tmp), L"bt[%lu,%u]", bt, len); + name = tmp; + } + X(WCHAR*) = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name) + 1) * sizeof(WCHAR)); + if (X(WCHAR*)) + lstrcpyW(X(WCHAR*), name); + return TRUE; +} + +BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo) +{ + if (type->id == dbg_itype_none) return FALSE; + if (type->module != 0) + return lookup_base_type_in_data_model(type, ti, pInfo) || + SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
assert(type->id >= dbg_itype_first);
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- programs/winedbg/debugger.h | 4 ++++ programs/winedbg/types.c | 10 ++++++---- programs/winedbg/winedbg.c | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index de6c8b3e438..ac13a28e3ca 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -265,6 +265,7 @@ struct dbg_process char source_current_file[MAX_PATH]; int source_start_line; int source_end_line; + const struct data_model* data_model; };
/* describes the way the debugger interacts with a given process */ @@ -550,6 +551,9 @@ struct data_model unsigned size; const WCHAR* name; }; +extern const struct data_model ilp32_data_model[]; +extern const struct data_model lp64_data_model[]; +extern const struct data_model llp64_data_model[];
extern struct dbg_internal_var dbg_internal_vars[];
diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index f4ee5a011d5..899e7f472b2 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -714,7 +714,7 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) return TRUE; }
-static const struct data_model ilp32_data_model[] = { +const struct data_model ilp32_data_model[] = { {btVoid, 0, L"void"}, {btChar, 1, L"char"}, {btWChar, 2, L"wchar_t"}, @@ -741,7 +741,7 @@ static const struct data_model ilp32_data_model[] = { {0, 0, NULL} };
-static const struct data_model llp64_data_model[] = { +const struct data_model llp64_data_model[] = { {btVoid, 0, L"void"}, {btChar, 1, L"char"}, {btWChar, 2, L"wchar_t"}, @@ -770,7 +770,7 @@ static const struct data_model llp64_data_model[] = { {0, 0, NULL} };
-static const struct data_model lp64_data_model[] = { +const struct data_model lp64_data_model[] = { {btVoid, 0, L"void"}, {btChar, 1, L"char"}, {btWChar, 2, L"wchar_t"}, @@ -803,7 +803,9 @@ static const struct data_model* get_data_model(DWORD modaddr) { const struct data_model *model;
- if (ADDRSIZE == 4) model = ilp32_data_model; + if (dbg_curr_process->data_model) + model = dbg_curr_process->data_model; + else if (ADDRSIZE == 4) model = ilp32_data_model; else { IMAGEHLP_MODULEW64 mi; diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index d11b68ec432..8a5c9bc69ed 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -284,6 +284,7 @@ struct dbg_process* dbg_add_process(const struct be_process_io* pio, DWORD pid, p->source_current_file[0] = '\0'; p->source_start_line = -1; p->source_end_line = -1; + p->data_model = NULL;
list_add_head(&dbg_process_list, &p->entry);
@@ -467,6 +468,29 @@ void dbg_set_option(const char* option, const char* val) return; } } + else if (!strcasecmp(option, "data_model")) + { + if (!dbg_curr_process) + { + dbg_printf("Not attached to a process\n"); + return; + } + if (!val) + { + const char* model = ""; + if (dbg_curr_process->data_model == NULL) model = "auto"; + else if (dbg_curr_process->data_model == ilp32_data_model) model = "ilp32"; + else if (dbg_curr_process->data_model == llp64_data_model) model = "llp64"; + else if (dbg_curr_process->data_model == lp64_data_model) model = "lp64"; + dbg_printf("Option: data_model %s\n", model); + } + else if (!strcasecmp(val, "auto")) dbg_curr_process->data_model = NULL; + else if (!strcasecmp(val, "ilp32")) dbg_curr_process->data_model = ilp32_data_model; + else if (!strcasecmp(val, "llp64")) dbg_curr_process->data_model = llp64_data_model; + else if (!strcasecmp(val, "lp64")) dbg_curr_process->data_model = lp64_data_model; + else + dbg_printf("Unknown data model %s\n", val); + } else dbg_printf("Unknown option '%s'\n", option); }
From: Eric Pouech eric.pouech@gmail.com
rationale: - native doesn't report names for SymTagBaseType objects => so remove typename for sym_basic - since symt_basic becomes pretty simple, it's possible to share the object across all modules loaded in dbghelp (simplicity, memory usage reduction) - removed dwarf basic types cache in dwarf.c as we now have a generic one
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/dbghelp_private.h | 4 +-- dlls/dbghelp/dwarf.c | 46 +++++++++++----------------- dlls/dbghelp/msc.c | 56 +++++++++++++++++----------------- dlls/dbghelp/stabs.c | 48 ++++++++++++++--------------- dlls/dbghelp/type.c | 37 ++++++++++------------ 5 files changed, 87 insertions(+), 104 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 507724414a5..24ac003df71 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -336,7 +336,6 @@ struct symt_array struct symt_basic { struct symt symt; - struct hash_table_elt hash_elt; enum BasicType bt; ULONG_PTR size; }; @@ -901,8 +900,7 @@ extern void symt_init_basic(struct module* module) DECLSPEC_HIDDEN; extern BOOL symt_get_info(struct module* module, const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo) DECLSPEC_HIDDEN; extern struct symt_basic* - symt_new_basic(struct module* module, enum BasicType, - const char* typename, unsigned size) DECLSPEC_HIDDEN; + symt_get_basic(enum BasicType, unsigned size) DECLSPEC_HIDDEN; extern struct symt_udt* symt_new_udt(struct module* module, const char* typename, unsigned size, enum UdtKind kind) DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index b81f83ac90b..19c0da933d3 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -162,11 +162,6 @@ typedef struct dwarf2_traverse_context_s const unsigned char* end_data; } dwarf2_traverse_context_t;
-/* symt_cache indexes */ -#define sc_void 0 -#define sc_unknown 1 -#define sc_num 2 - typedef struct dwarf2_cuhead_s { unsigned char word_size; /* size of a word on target machine */ @@ -180,7 +175,6 @@ typedef struct dwarf2_parse_module_context_s const dwarf2_section_t* sections; struct module* module; const struct elf_thunk_area*thunks; - struct symt* symt_cache[sc_num]; /* void, unknown */ struct vector unit_contexts; struct dwarf2_dwz_alternate_s* dwz; DWORD cu_versions; @@ -1138,14 +1132,14 @@ static struct symt* dwarf2_lookup_type(const dwarf2_debug_info_t* di)
if (!dwarf2_find_attribute(di, DW_AT_type, &attr)) /* this is only valid if current language of CU is C or C++ */ - return di->unit_ctx->module_ctx->symt_cache[sc_void]; + return &symt_get_basic(btVoid, 0)->symt; if (!(type = dwarf2_jump_to_debug_info(&attr))) - return di->unit_ctx->module_ctx->symt_cache[sc_unknown]; + return &symt_get_basic(btNoType, 0)->symt;
if (type == di) { FIXME("Reference to itself\n"); - return di->unit_ctx->module_ctx->symt_cache[sc_unknown]; + return &symt_get_basic(btNoType, 0)->symt; } if (!type->symt) { @@ -1154,7 +1148,7 @@ static struct symt* dwarf2_lookup_type(const dwarf2_debug_info_t* di) if (!type->symt) { FIXME("Unable to load forward reference for tag %Ix\n", type->abbrev->tag); - return di->unit_ctx->module_ctx->symt_cache[sc_unknown]; + return &symt_get_basic(btNoType, 0)->symt; } } return type->symt; @@ -1484,7 +1478,7 @@ static struct symt* dwarf2_parse_base_type(dwarf2_debug_info_t* di) case DW_ATE_unsigned_char: bt = btChar; break; default: bt = btNoType; break; } - di->symt = &symt_new_basic(di->unit_ctx->module_ctx->module, bt, name.u.string, size.u.uvalue)->symt; + di->symt = &symt_get_basic(bt, size.u.uvalue)->symt;
if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); return di->symt; @@ -1566,14 +1560,14 @@ static struct symt* dwarf2_parse_array_type(dwarf2_debug_info_t* di) { /* fake an array with unknown size */ /* FIXME: int4 even on 64bit machines??? */ - idx_type = &symt_new_basic(di->unit_ctx->module_ctx->module, btInt, "int", 4)->symt; + idx_type = &symt_get_basic(btInt, 4)->symt; min.u.uvalue = 0; cnt.u.uvalue = 0; } else for (i = 0; i < vector_length(children); i++) { child = *(dwarf2_debug_info_t**)vector_at(children, i); - if (child->symt == di->unit_ctx->module_ctx->symt_cache[sc_unknown]) continue; + if (child->symt == &symt_get_basic(btNoType, 0)->symt) continue; switch (child->abbrev->tag) { case DW_TAG_subrange_type: @@ -1665,19 +1659,18 @@ static struct symt* dwarf2_parse_restrict_type(dwarf2_debug_info_t* di) static struct symt* dwarf2_parse_unspecified_type(dwarf2_debug_info_t* di) { struct attribute name; - struct attribute size; - struct symt_basic *basic; + struct symt* basic;
TRACE("%s\n", dwarf2_debug_di(di));
if (di->symt) return di->symt;
- if (!dwarf2_find_attribute(di, DW_AT_name, &name)) - name.u.string = "void"; - size.u.uvalue = di->unit_ctx->module_ctx->module->cpu->word_size; - - basic = symt_new_basic(di->unit_ctx->module_ctx->module, btVoid, name.u.string, size.u.uvalue); - di->symt = &basic->symt; + basic = &symt_get_basic(btVoid, 0)->symt; + if (dwarf2_find_attribute(di, DW_AT_name, &name)) + /* define the missing type as a typedef to void... */ + di->symt = &symt_new_typedef(di->unit_ctx->module_ctx->module, basic, name.u.string)->symt; + else /* or use void if it doesn't even have a name */ + di->symt = basic;
if (dwarf2_get_di_children(di)) FIXME("Unsupported children\n"); return di->symt; @@ -1878,10 +1871,10 @@ static struct symt* dwarf2_parse_enumeration_type(dwarf2_debug_info_t* di)
switch (size.u.uvalue) /* FIXME: that's wrong */ { - case 1: basetype = symt_new_basic(di->unit_ctx->module_ctx->module, btInt, "char", 1); break; - case 2: basetype = symt_new_basic(di->unit_ctx->module_ctx->module, btInt, "short", 2); break; + case 1: basetype = symt_get_basic(btInt, 1); break; + case 2: basetype = symt_get_basic(btInt, 2); break; default: - case 4: basetype = symt_new_basic(di->unit_ctx->module_ctx->module, btInt, "int", 4); break; + case 4: basetype = symt_get_basic(btInt, 4); break; } type = &basetype->symt; } @@ -2457,7 +2450,7 @@ static void dwarf2_parse_namespace(dwarf2_debug_info_t* di)
TRACE("%s\n", dwarf2_debug_di(di));
- di->symt = di->unit_ctx->module_ctx->symt_cache[sc_void]; + di->symt = &symt_get_basic(btVoid, 0)->symt;
children = dwarf2_get_di_children(di); if (children) for (i = 0; i < vector_length(children); i++) @@ -4071,9 +4064,6 @@ static BOOL dwarf2_load_CU_module(dwarf2_parse_module_context_t* module_ctx, str module_ctx->module = module; module_ctx->thunks = thunks; module_ctx->load_offset = load_offset; - memset(module_ctx->symt_cache, 0, sizeof(module_ctx->symt_cache)); - module_ctx->symt_cache[sc_void] = &symt_new_basic(module_ctx->module, btVoid, "void", 0)->symt; - module_ctx->symt_cache[sc_unknown] = &symt_new_basic(module_ctx->module, btNoType, "# unknown", 0)->symt; vector_init(&module_ctx->unit_contexts, sizeof(dwarf2_parse_context_t), 16); module_ctx->cu_versions = 0;
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 22ab1ecb230..64d520c2b37 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -157,34 +157,34 @@ static void codeview_init_basic_types(struct module* module) */ cv_basic_types[T_NOTYPE] = NULL; cv_basic_types[T_ABS] = NULL; - cv_basic_types[T_VOID] = &symt_new_basic(module, btVoid, "void", 0)->symt; - cv_basic_types[T_CHAR] = &symt_new_basic(module, btChar, "char", 1)->symt; - cv_basic_types[T_SHORT] = &symt_new_basic(module, btInt, "short int", 2)->symt; - cv_basic_types[T_LONG] = &symt_new_basic(module, btInt, "long int", 4)->symt; - cv_basic_types[T_QUAD] = &symt_new_basic(module, btInt, "long long int", 8)->symt; - cv_basic_types[T_UCHAR] = &symt_new_basic(module, btUInt, "unsigned char", 1)->symt; - cv_basic_types[T_USHORT] = &symt_new_basic(module, btUInt, "unsigned short", 2)->symt; - cv_basic_types[T_ULONG] = &symt_new_basic(module, btUInt, "unsigned long", 4)->symt; - cv_basic_types[T_UQUAD] = &symt_new_basic(module, btUInt, "unsigned long long", 8)->symt; - cv_basic_types[T_BOOL08] = &symt_new_basic(module, btBool, "BOOL08", 1)->symt; - cv_basic_types[T_BOOL16] = &symt_new_basic(module, btBool, "BOOL16", 2)->symt; - cv_basic_types[T_BOOL32] = &symt_new_basic(module, btBool, "BOOL32", 4)->symt; - cv_basic_types[T_BOOL64] = &symt_new_basic(module, btBool, "BOOL64", 8)->symt; - cv_basic_types[T_REAL32] = &symt_new_basic(module, btFloat, "float", 4)->symt; - cv_basic_types[T_REAL64] = &symt_new_basic(module, btFloat, "double", 8)->symt; - cv_basic_types[T_REAL80] = &symt_new_basic(module, btFloat, "long double", 10)->symt; - cv_basic_types[T_RCHAR] = &symt_new_basic(module, btInt, "signed char", 1)->symt; - cv_basic_types[T_WCHAR] = &symt_new_basic(module, btWChar, "wchar_t", 2)->symt; - cv_basic_types[T_CHAR16] = &symt_new_basic(module, btChar16,"char16_t", 2)->symt; - cv_basic_types[T_CHAR32] = &symt_new_basic(module, btChar32,"char32_t", 4)->symt; - cv_basic_types[T_CHAR8] = &symt_new_basic(module, btChar8, "char8_t", 1)->symt; - cv_basic_types[T_INT2] = &symt_new_basic(module, btInt, "INT2", 2)->symt; - cv_basic_types[T_UINT2] = &symt_new_basic(module, btUInt, "UINT2", 2)->symt; - cv_basic_types[T_INT4] = &symt_new_basic(module, btInt, "INT4", 4)->symt; - cv_basic_types[T_UINT4] = &symt_new_basic(module, btUInt, "UINT4", 4)->symt; - cv_basic_types[T_INT8] = &symt_new_basic(module, btInt, "INT8", 8)->symt; - cv_basic_types[T_UINT8] = &symt_new_basic(module, btUInt, "UINT8", 8)->symt; - cv_basic_types[T_HRESULT]= &symt_new_basic(module, btUInt, "HRESULT", 4)->symt; + cv_basic_types[T_VOID] = &symt_get_basic(btVoid, 0)->symt; /* void */ + cv_basic_types[T_CHAR] = &symt_get_basic(btChar, 1)->symt; /* char */ + cv_basic_types[T_SHORT] = &symt_get_basic(btInt, 2)->symt; /* short int */ + cv_basic_types[T_LONG] = &symt_get_basic(btInt, 4)->symt; /* long int */ + cv_basic_types[T_QUAD] = &symt_get_basic(btInt, 8)->symt; /* long long int */ + cv_basic_types[T_UCHAR] = &symt_get_basic(btUInt, 1)->symt; /* unsigned char */ + cv_basic_types[T_USHORT] = &symt_get_basic(btUInt, 2)->symt; /* unsigned short */ + cv_basic_types[T_ULONG] = &symt_get_basic(btUInt, 4)->symt; /* unsigned long */ + cv_basic_types[T_UQUAD] = &symt_get_basic(btUInt, 8)->symt; /* unsigned long long */ + cv_basic_types[T_BOOL08] = &symt_get_basic(btBool, 1)->symt; /* BOOL08 */ + cv_basic_types[T_BOOL16] = &symt_get_basic(btBool, 2)->symt; /* BOOL16 */ + cv_basic_types[T_BOOL32] = &symt_get_basic(btBool, 4)->symt; /* BOOL32 */ + cv_basic_types[T_BOOL64] = &symt_get_basic(btBool, 8)->symt; /* BOOL64 */ + cv_basic_types[T_REAL32] = &symt_get_basic(btFloat, 4)->symt; /* float */ + cv_basic_types[T_REAL64] = &symt_get_basic(btFloat, 8)->symt; /* double */ + cv_basic_types[T_REAL80] = &symt_get_basic(btFloat, 10)->symt; /* long double */ + cv_basic_types[T_RCHAR] = &symt_get_basic(btInt, 1)->symt; /* signed char */ + cv_basic_types[T_WCHAR] = &symt_get_basic(btWChar, 2)->symt; /* char8_t */ + cv_basic_types[T_CHAR16] = &symt_get_basic(btChar16, 2)->symt; /* char16_t */ + cv_basic_types[T_CHAR32] = &symt_get_basic(btChar32, 4)->symt; /* char32_t */ + cv_basic_types[T_CHAR8] = &symt_get_basic(btChar8, 1)->symt; /* char8_t */ + cv_basic_types[T_INT2] = &symt_get_basic(btInt, 2)->symt; /* INT2 */ + cv_basic_types[T_UINT2] = &symt_get_basic(btUInt, 2)->symt; /* UINT2 */ + cv_basic_types[T_INT4] = &symt_get_basic(btInt, 4)->symt; /* INT4 */ + cv_basic_types[T_UINT4] = &symt_get_basic(btUInt, 4)->symt; /* UINT4 */ + cv_basic_types[T_INT8] = &symt_get_basic(btInt, 8)->symt; /* INT8 */ + cv_basic_types[T_UINT8] = &symt_get_basic(btUInt, 8)->symt; /* UINT8 */ + cv_basic_types[T_HRESULT]= &symt_get_basic(btUInt, 4)->symt; /* HRESULT */
cv_basic_types[T_32PVOID] = &symt_new_pointer(module, cv_basic_types[T_VOID], 4)->symt; cv_basic_types[T_32PCHAR] = &symt_new_pointer(module, cv_basic_types[T_CHAR], 4)->symt; diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index 89ae0951a6a..b22fb714973 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -322,31 +322,31 @@ static int stabs_get_basic(struct ParseTypedefData* ptd, unsigned basic, struct { switch (basic) { - case 1: stabs_basic[basic] = symt_new_basic(ptd->module, btInt, "int", 4); break; - case 2: stabs_basic[basic] = symt_new_basic(ptd->module, btChar, "char", 1); break; - case 3: stabs_basic[basic] = symt_new_basic(ptd->module, btInt, "short int", 2); break; - case 4: stabs_basic[basic] = symt_new_basic(ptd->module, btInt, "long int", 4); break; - case 5: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt, "unsigned char", 1); break; - case 6: stabs_basic[basic] = symt_new_basic(ptd->module, btInt, "signed char", 1); break; - case 7: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt, "unsigned short int", 2); break; - case 8: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt, "unsigned int", 4); break; - case 9: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt, "unsigned", 2); break; - case 10: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt, "unsigned long int", 2); break; - case 11: stabs_basic[basic] = symt_new_basic(ptd->module, btVoid, "void", 0); break; - case 12: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat, "float", 4); break; - case 13: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat, "double", 8); break; - case 14: stabs_basic[basic] = symt_new_basic(ptd->module, btFloat, "long double", 12); break; - case 15: stabs_basic[basic] = symt_new_basic(ptd->module, btInt, "integer", 4); break; - case 16: stabs_basic[basic] = symt_new_basic(ptd->module, btBool, "bool", 1); break; + case 1: stabs_basic[basic] = symt_get_basic(btInt, 4); break; /* int */ + case 2: stabs_basic[basic] = symt_get_basic(btChar, 1); break; /* char */ + case 3: stabs_basic[basic] = symt_get_basic(btInt, 2); break; /* short int */ + case 4: stabs_basic[basic] = symt_get_basic(btInt, 4); break; /* long int */ + case 5: stabs_basic[basic] = symt_get_basic(btUInt, 1); break; /* unsigned char */ + case 6: stabs_basic[basic] = symt_get_basic(btInt, 1); break; /* signed char */ + case 7: stabs_basic[basic] = symt_get_basic(btUInt, 2); break; /* unsigned short int */ + case 8: stabs_basic[basic] = symt_get_basic(btUInt, 4); break; /* unsigned int */ + case 9: stabs_basic[basic] = symt_get_basic(btUInt, 2); break; /* unsigned */ + case 10: stabs_basic[basic] = symt_get_basic(btUInt, 2); break; /* unsigned long int */ + case 11: stabs_basic[basic] = symt_get_basic(btVoid, 0); break; /* void */ + case 12: stabs_basic[basic] = symt_get_basic(btFloat, 4); break; /* float */ + case 13: stabs_basic[basic] = symt_get_basic(btFloat, 8); break; /* double */ + case 14: stabs_basic[basic] = symt_get_basic(btFloat, 2); break; /* long double", */ + case 15: stabs_basic[basic] = symt_get_basic(btInt, 4); break; /* integer */ + case 16: stabs_basic[basic] = symt_get_basic(btBool, 1); break; /* bool */ /* case 17: short real */ /* case 18: real */ - case 25: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "float complex", 8); break; - case 26: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "double complex", 16); break; - case 30: stabs_basic[basic] = symt_new_basic(ptd->module, btWChar, "wchar_t", 2); break; - case 31: stabs_basic[basic] = symt_new_basic(ptd->module, btInt, "long long int", 8); break; - case 32: stabs_basic[basic] = symt_new_basic(ptd->module, btUInt, "long long unsigned", 8); break; + case 25: stabs_basic[basic] = symt_get_basic(btComplex, 8); break; /* float complex */ + case 26: stabs_basic[basic] = symt_get_basic(btComplex, 6); break; /* double complex", */ + case 30: stabs_basic[basic] = symt_get_basic(btWChar, 2); break; /* wchar_t */ + case 31: stabs_basic[basic] = symt_get_basic(btInt, 8); break; /* long long int */ + case 32: stabs_basic[basic] = symt_get_basic(btUInt, 8); break; /* long long unsigned */ /* starting at 35 are wine extensions (especially for R implementation) */ - case 35: stabs_basic[basic] = symt_new_basic(ptd->module, btComplex, "long double complex", 24); break; + case 35: stabs_basic[basic] = symt_get_basic(btComplex, 4); break; /* long double complex", */ default: PTS_ABORTIF(ptd, 1); } } @@ -541,7 +541,7 @@ static int stabs_pts_read_range(struct ParseTypedefData* ptd, const char* typena } else PTS_ABORTIF(ptd, 1);
- *dt = &symt_new_basic(ptd->module, bt, typename, size)->symt; + *dt = &symt_get_basic(bt, size)->symt; return 0; }
@@ -967,7 +967,7 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ */ if (!new_dt && typename) { - new_dt = &symt_new_basic(ptd->module, btVoid, typename, 0)->symt; + new_dt = &symt_get_basic(btVoid, 0)->symt; PTS_ABORTIF(ptd, strcmp(typename, "void")); } } diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index 67f4265ddc9..0cbbc4e333b 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -97,7 +97,6 @@ const char* symt_get_name(const struct symt* sym) case SymTagFunction: return ((const struct symt_function*)sym)->hash_elt.name; case SymTagInlineSite: return ((const struct symt_inlinesite*)sym)->func.hash_elt.name; case SymTagPublicSymbol: return ((const struct symt_public*)sym)->hash_elt.name; - case SymTagBaseType: return ((const struct symt_basic*)sym)->hash_elt.name; case SymTagLabel: return ((const struct symt_hierarchy_point*)sym)->hash_elt.name; case SymTagThunk: return ((const struct symt_thunk*)sym)->hash_elt.name; case SymTagCustom: return ((const struct symt_custom*)sym)->hash_elt.name; @@ -110,6 +109,7 @@ const char* symt_get_name(const struct symt* sym) default: FIXME("Unsupported sym-tag %s\n", symt_get_tag_str(sym->tag)); /* fall through */ + case SymTagBaseType: case SymTagArrayType: case SymTagPointerType: case SymTagFunctionType: @@ -224,31 +224,26 @@ static void symt_add_type(struct module* module, struct symt* symt) *p = symt; }
-struct symt_basic* symt_new_basic(struct module* module, enum BasicType bt, - const char* typename, unsigned size) +struct symt_basic* symt_get_basic(enum BasicType bt, unsigned size) { - struct symt_basic* sym; + static struct symt_basic cache[32] = { { {SymTagBaseType}, btNoType, 0 } }; + int i;
- if (typename) - { - sym = (struct symt_basic*)symt_find_type_by_name(module, SymTagBaseType, - typename); - if (sym && sym->bt == bt && sym->size == size) - return sym; - } - if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) + if (bt == btNoType) return &cache[0]; + for (i = 1; i < ARRAY_SIZE(cache); i++) { - sym->symt.tag = SymTagBaseType; - if (typename) + if (cache[i].bt == btNoType) /* empty slot, create new entry */ { - sym->hash_elt.name = pool_strdup(&module->pool, typename); - hash_table_add(&module->ht_types, &sym->hash_elt); - } else sym->hash_elt.name = NULL; - sym->bt = bt; - sym->size = size; - symt_add_type(module, &sym->symt); + cache[i].symt.tag = SymTagBaseType; + cache[i].bt = bt; + cache[i].size = size; + return &cache[i]; + } + if (cache[i].bt == bt && cache[i].size == size) + return &cache[i]; } - return sym; + FIXME("Too few slots in basic types cache\n"); + return &cache[0]; }
struct symt_udt* symt_new_udt(struct module* module, const char* typename,
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- 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);
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/msc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 64d520c2b37..5b45c474160 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -158,13 +158,13 @@ static void codeview_init_basic_types(struct module* module) cv_basic_types[T_NOTYPE] = NULL; cv_basic_types[T_ABS] = NULL; cv_basic_types[T_VOID] = &symt_get_basic(btVoid, 0)->symt; /* void */ - cv_basic_types[T_CHAR] = &symt_get_basic(btChar, 1)->symt; /* char */ + cv_basic_types[T_CHAR] = &symt_get_basic(btInt, 1)->symt; /* signed char (and char in C) */ cv_basic_types[T_SHORT] = &symt_get_basic(btInt, 2)->symt; /* short int */ - cv_basic_types[T_LONG] = &symt_get_basic(btInt, 4)->symt; /* long int */ + cv_basic_types[T_LONG] = &symt_get_basic(btLong, 4)->symt; /* long int */ cv_basic_types[T_QUAD] = &symt_get_basic(btInt, 8)->symt; /* long long int */ cv_basic_types[T_UCHAR] = &symt_get_basic(btUInt, 1)->symt; /* unsigned char */ cv_basic_types[T_USHORT] = &symt_get_basic(btUInt, 2)->symt; /* unsigned short */ - cv_basic_types[T_ULONG] = &symt_get_basic(btUInt, 4)->symt; /* unsigned long */ + cv_basic_types[T_ULONG] = &symt_get_basic(btULong, 4)->symt; /* unsigned long */ cv_basic_types[T_UQUAD] = &symt_get_basic(btUInt, 8)->symt; /* unsigned long long */ cv_basic_types[T_BOOL08] = &symt_get_basic(btBool, 1)->symt; /* BOOL08 */ cv_basic_types[T_BOOL16] = &symt_get_basic(btBool, 2)->symt; /* BOOL16 */ @@ -173,7 +173,7 @@ static void codeview_init_basic_types(struct module* module) cv_basic_types[T_REAL32] = &symt_get_basic(btFloat, 4)->symt; /* float */ cv_basic_types[T_REAL64] = &symt_get_basic(btFloat, 8)->symt; /* double */ cv_basic_types[T_REAL80] = &symt_get_basic(btFloat, 10)->symt; /* long double */ - cv_basic_types[T_RCHAR] = &symt_get_basic(btInt, 1)->symt; /* signed char */ + cv_basic_types[T_RCHAR] = &symt_get_basic(btChar, 1)->symt; /* "real" char (char in C++) */ cv_basic_types[T_WCHAR] = &symt_get_basic(btWChar, 2)->symt; /* char8_t */ cv_basic_types[T_CHAR16] = &symt_get_basic(btChar16, 2)->symt; /* char16_t */ cv_basic_types[T_CHAR32] = &symt_get_basic(btChar32, 4)->symt; /* char32_t */