From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp.c | 7 ++++ dlls/dbghelp/dbghelp.spec | 3 ++ dlls/dbghelp/dbghelp_private.h | 10 ++--- dlls/dbghelp/dwarf.c | 25 ++++++------ dlls/dbghelp/module.c | 33 ++++++++++++++++ dlls/dbghelp/stabs.c | 2 +- include/Makefile.in | 1 + include/dbghelp.h | 2 + include/wine/dbghelp_ext.h | 51 +++++++++++++++++++++++++ programs/winedbg/info.c | 70 +++++++++++++++++----------------- programs/winedbg/winedbg.c | 1 + 11 files changed, 149 insertions(+), 56 deletions(-) create mode 100644 include/wine/dbghelp_ext.h
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index d0f711761d4..4e6938cb557 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -67,6 +67,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
unsigned dbghelp_options = SYMOPT_UNDNAME; BOOL dbghelp_opt_native = FALSE; +BOOL dbghelp_opt_extension_api = FALSE; BOOL dbghelp_opt_real_path = FALSE; BOOL dbghelp_opt_source_actual_path = FALSE; SYSTEM_INFO sysinfo; @@ -612,6 +613,10 @@ BOOL WINAPI SymSetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option, BOOL value) old = dbghelp_opt_native; dbghelp_opt_native = value; break; + case SYMOPT_EX_WINE_EXTENSION_API: + old = dbghelp_opt_extension_api; + dbghelp_opt_extension_api = value; + break; case SYMOPT_EX_WINE_MODULE_REAL_PATH: old = dbghelp_opt_real_path; dbghelp_opt_real_path = value; @@ -637,6 +642,8 @@ BOOL WINAPI SymGetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option) { case SYMOPT_EX_WINE_NATIVE_MODULES: return dbghelp_opt_native; + case SYMOPT_EX_WINE_EXTENSION_API: + return dbghelp_opt_extension_api; case SYMOPT_EX_WINE_MODULE_REAL_PATH: return dbghelp_opt_real_path; case SYMOPT_EX_WINE_SOURCE_ACTUAL_PATH: diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec index 9ef5922386e..a89c2c1d86b 100644 --- a/dlls/dbghelp/dbghelp.spec +++ b/dlls/dbghelp/dbghelp.spec @@ -215,3 +215,6 @@ #@ stub sym #@ stub symsrv #@ stub vc7fpo + +# wine extensions +@ stdcall wine_get_module_information(long int64 ptr long) diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index c6d144bb175..a7ec4bcc426 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -31,6 +31,7 @@ #include "winnls.h" #include "wine/list.h" #include "wine/rbtree.h" +#include "wine/dbghelp_ext.h"
#include "cvconst.h"
@@ -112,6 +113,7 @@ void* hash_table_iter_up(struct hash_table_iter* hti) DECLSPEC_HIDDEN;
extern unsigned dbghelp_options DECLSPEC_HIDDEN; extern BOOL dbghelp_opt_native DECLSPEC_HIDDEN; +extern BOOL dbghelp_opt_extension_api DECLSPEC_HIDDEN; extern BOOL dbghelp_opt_real_path DECLSPEC_HIDDEN; extern BOOL dbghelp_opt_source_actual_path DECLSPEC_HIDDEN; extern SYSTEM_INFO sysinfo DECLSPEC_HIDDEN; @@ -396,13 +398,6 @@ struct symt_udt struct vector vchildren; };
-enum module_type -{ - DMT_ELF, /* a real ELF shared module */ - DMT_PE, /* a native or builtin PE module */ - DMT_MACHO, /* a real Mach-O shared module */ -}; - struct process; struct module;
@@ -453,6 +448,7 @@ struct module
/* specific information for debug types */ struct module_format* format_info[DFI_LAST]; + unsigned debug_format_bitmask;
/* memory allocation pool */ struct pool pool; diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 2a4f9a16228..332c3da1059 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2892,8 +2892,8 @@ static BOOL dwarf2_parse_compilation_unit_head(dwarf2_parse_context_t* ctx, TRACE("- word_size: %u\n", ctx->head.word_size); TRACE("- offset_size: %u\n", ctx->head.offset_size);
- if (ctx->head.version >= 2) - ctx->module_ctx->cu_versions |= 1 << (ctx->head.version - 2); + if (ctx->head.version >= 2 && ctx->head.version <= 5) + ctx->module_ctx->cu_versions |= DHEXT_FORMAT_DWARF2 << (ctx->head.version - 2); if (max_supported_dwarf_version == 0) { char* env = getenv("DBGHELP_DWARF_VERSION"); @@ -4259,17 +4259,16 @@ BOOL dwarf2_parse(struct module* module, ULONG_PTR load_offset, module_ctx.dwz = dwarf2_load_dwz(fmap, module); dwarf2_load_CU_module(&module_ctx, module, section, load_offset, thunks, FALSE);
- dwarf2_modfmt->module->module.SymType = SymDia; - /* hide dwarf versions in CVSig - * bits 24-31 will be set according to found dwarf version - * different CU can have different dwarf version, so use a bit per version (version 2 => b24) - */ - dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('F' << 16) | ((module_ctx.cu_versions & 0xFF) << 24); - /* FIXME: we could have a finer grain here */ - dwarf2_modfmt->module->module.GlobalSymbols = TRUE; - dwarf2_modfmt->module->module.TypeInfo = TRUE; - dwarf2_modfmt->module->module.SourceIndexed = TRUE; - dwarf2_modfmt->module->module.Publics = TRUE; + if (module_ctx.cu_versions) + { + dwarf2_modfmt->module->module.SymType = SymDia; + module->debug_format_bitmask |= module_ctx.cu_versions; + /* FIXME: we could have a finer grain here */ + dwarf2_modfmt->module->module.GlobalSymbols = TRUE; + dwarf2_modfmt->module->module.TypeInfo = TRUE; + dwarf2_modfmt->module->module.SourceIndexed = TRUE; + dwarf2_modfmt->module->module.Publics = TRUE; + }
dwarf2_unload_CU_module(&module_ctx); leave: diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index e6ee9534ff4..469f911707a 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -238,6 +238,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name, module->cpu = cpu_find(machine); if (!module->cpu) module->cpu = dbghelp_current_cpu; + module->debug_format_bitmask = 0;
vector_init(&module->vsymt, sizeof(struct symt*), 128); vector_init(&module->vcustom_symt, sizeof(struct symt*), 16); @@ -1653,3 +1654,35 @@ const struct loader_ops empty_loader_ops = empty_enum_modules, native_fetch_file_info, }; + +BOOL WINAPI wine_get_module_information(HANDLE proc, DWORD64 base, struct dhext_module_information* wmi, unsigned len) +{ + struct process* pcs; + struct module* module; + struct dhext_module_information dhmi; + + /* could be interpreted as a WinDbg extension */ + if (!dbghelp_opt_extension_api) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + TRACE("(%p %I64x %p %u\n", proc, base, wmi, len); + + if (!(pcs = process_find_by_handle(proc))) return FALSE; + if (len > sizeof(*wmi)) return FALSE; + + module = module_find_by_addr(pcs, base); + if (!module) return FALSE; + + dhmi.type = module->type; + dhmi.debug_format_bitmask = module->debug_format_bitmask; + if ((module = module_get_container(pcs, module))) + { + dhmi.debug_format_bitmask |= module->debug_format_bitmask; + } + memcpy(wmi, &dhmi, len); + + return TRUE; +} diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index f21f7e15d0b..552b334f2da 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1664,7 +1664,7 @@ BOOL stabs_parse(struct module* module, ULONG_PTR load_offset, stab_ptr->n_type, (ULONG_PTR)n_value, debugstr_a(strs + stab_ptr->n_strx)); } module->module.SymType = SymDia; - module->module.CVSig = 'S' | ('T' << 8) | ('A' << 16) | ('B' << 24); + module->debug_format_bitmask |= DHEXT_FORMAT_STABS; /* FIXME: we could have a finer grain here */ module->module.LineNumbers = TRUE; module->module.GlobalSymbols = TRUE; diff --git a/include/Makefile.in b/include/Makefile.in index 4fdee0c9b91..c508057fc1c 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -879,6 +879,7 @@ SOURCES = \ wine/asm.h \ wine/atsvc.idl \ wine/condrv.h \ + wine/dbghelp_ext.h \ wine/dcetypes.idl \ wine/debug.h \ wine/dplaysp.h \ diff --git a/include/dbghelp.h b/include/dbghelp.h index 15e9f9d2d77..f87dfe777ba 100644 --- a/include/dbghelp.h +++ b/include/dbghelp.h @@ -1102,6 +1102,8 @@ typedef enum #ifdef __WINESRC__ /* Include ELF/Mach-O modules in module operations */ SYMOPT_EX_WINE_NATIVE_MODULES = 1000, + /* Enable Wine's extension APIs */ + SYMOPT_EX_WINE_EXTENSION_API, /* Return the Unix actual path of loaded module */ SYMOPT_EX_WINE_MODULE_REAL_PATH, /* Return the raw source file path from debug info (not always mapped to DOS) */ diff --git a/include/wine/dbghelp_ext.h b/include/wine/dbghelp_ext.h new file mode 100644 index 00000000000..389b0f99fa0 --- /dev/null +++ b/include/wine/dbghelp_ext.h @@ -0,0 +1,51 @@ +/* + * Declarations for DBGHELP Wine's extensions + * + * Copyright (C) 2023 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_DBGHELP_EXT_H +#define __WINE_DBGHELP_EXT_H + +#include <winbase.h> + +enum module_type +{ + DMT_UNKNOWN, /* for lookup, not actually used for a module */ + DMT_ELF, /* a real ELF shared module */ + DMT_MACHO, /* a real Mach-O shared module */ + DMT_PE, /* a native or builtin PE module */ +}; + +/* only reporting the formats not exposed in regular IMAGHELP_MODULE_INFO */ +enum dhext_debug_format +{ + DHEXT_FORMAT_DWARF2 = 0x0001, + DHEXT_FORMAT_DWARF3 = 0x0002, + DHEXT_FORMAT_DWARF4 = 0x0004, + DHEXT_FORMAT_DWARF5 = 0x0008, + DHEXT_FORMAT_STABS = 0x0010, +}; + +struct dhext_module_information +{ + enum module_type type; + unsigned debug_format_bitmask; +}; + +extern BOOL WINAPI wine_get_module_information(HANDLE, DWORD64 base, struct dhext_module_information*, unsigned len); +#endif diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index 251b92c607b..1fa2076cbd2 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -29,6 +29,7 @@ #include "winuser.h" #include "tlhelp32.h" #include "wine/debug.h" +#include "wine/dbghelp_ext.h"
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
@@ -116,9 +117,23 @@ void info_help(void) while (infotext[i]) dbg_printf("%s\n", infotext[i++]); }
-static const char* get_symtype_str(const IMAGEHLP_MODULE64* mi) +struct info_module +{ + IMAGEHLP_MODULEW64 mi; + struct dhext_module_information ext_module_info; + char name[64]; +}; + +struct info_modules +{ + struct info_module *modules; + unsigned num_alloc; + unsigned num_used; +}; + +static const char* get_symtype_str(const struct info_module* im) { - switch (mi->SymType) + switch (im->mi.SymType) { default: case SymNone: return "--none--"; @@ -129,43 +144,26 @@ static const char* get_symtype_str(const IMAGEHLP_MODULE64* mi) case SymDeferred: return "Deferred"; case SymSym: return "Sym"; case SymDia: - switch (mi->CVSig) + if (im->ext_module_info.debug_format_bitmask) { - case 'S' | ('T' << 8) | ('A' << 16) | ('B' << 24): - return "Stabs"; - case 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24): - /* previous versions of dbghelp used to report this... */ - return "Dwarf"; - default: - if ((mi->CVSig & 0x00FFFFFF) == ('D' | ('W' << 8) | ('F' << 16))) + static char tmp[64]; + tmp[0] = '\0'; + if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_STABS) strcpy(tmp, "stabs"); + if (im->ext_module_info.debug_format_bitmask & (DHEXT_FORMAT_DWARF2 | DHEXT_FORMAT_DWARF3 | DHEXT_FORMAT_DWARF4 | DHEXT_FORMAT_DWARF5)) { - static char tmp[64]; - DWORD versbit = mi->CVSig >> 24; - strcpy(tmp, "Dwarf"); - if (versbit & 1) strcat(tmp, "-2"); - if (versbit & 2) strcat(tmp, "-3"); - if (versbit & 4) strcat(tmp, "-4"); - if (versbit & 8) strcat(tmp, "-5"); - return tmp; + if (tmp[0]) strcat(tmp, ", "); + strcat(tmp, "Dwarf"); + if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF2) strcat(tmp, "-2"); + if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF3) strcat(tmp, "-3"); + if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF4) strcat(tmp, "-4"); + if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF5) strcat(tmp, "-5"); } - return "DIA"; + return tmp; } + return "DIA"; } }
-struct info_module -{ - IMAGEHLP_MODULE64 mi; - char name[64]; -}; - -struct info_modules -{ - struct info_module *modules; - unsigned num_alloc; - unsigned num_used; -}; - static const char* get_machine_str(DWORD machine) { static char tmp[32]; @@ -187,12 +185,12 @@ static void module_print_info(const struct info_module *module, BOOL is_embedded module->mi.BaseOfImage, module->mi.BaseOfImage + module->mi.ImageSize, get_machine_str(module->mi.MachineType), - is_embedded ? "\" : get_symtype_str(&module->mi), module->name); + is_embedded ? "\" : get_symtype_str(module), module->name); else dbg_printf("%*.*I64x-%*.*I64x\t%-16s%s\n", ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage, ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage + module->mi.ImageSize, - is_embedded ? "\" : get_symtype_str(&module->mi), module->name); + is_embedded ? "\" : get_symtype_str(module), module->name); }
static int __cdecl module_compare(const void* p1, const void* p2) @@ -226,7 +224,9 @@ static BOOL CALLBACK info_mod_cb(PCSTR mod_name, DWORD64 base, PVOID ctx) im->modules = new; } im->modules[im->num_used].mi.SizeOfStruct = sizeof(im->modules[im->num_used].mi); - if (SymGetModuleInfo64(dbg_curr_process->handle, base, &im->modules[im->num_used].mi)) + if (SymGetModuleInfoW64(dbg_curr_process->handle, base, &im->modules[im->num_used].mi) && + wine_get_module_information(dbg_curr_process->handle, base, &im->modules[im->num_used].ext_module_info, + sizeof(im->modules[im->num_used].ext_module_info))) { const int dst_len = sizeof(im->modules[im->num_used].name); lstrcpynA(im->modules[im->num_used].name, mod_name, dst_len - 1); diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index 438d4a3d94b..92fa77429f6 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -723,6 +723,7 @@ int main(int argc, char** argv) SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS | SYMOPT_INCLUDE_32BIT_MODULES);
+ SymSetExtendedOption(SYMOPT_EX_WINE_EXTENSION_API, TRUE); SymSetExtendedOption(SYMOPT_EX_WINE_SOURCE_ACTUAL_PATH, TRUE);
if (argc && !strcmp(argv[0], "--auto"))