We used to have some hack for passing information (mainlyi module related ones) from dbghelp to WineDbg.
This series: - reimplements properly the sharing, introducing a Wine entrypoint to dbghelp (sharing debug formats not handled by native, no longer decorating module names for sharing that module was in fact a host module...) - improves "info share" command in WineDbg with more accurate information (host module type...) - improves loading time on MacOs (some system libraries no longer have their images accessible directly on disk by standard file operation).
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 4 +- dlls/dbghelp/msc.c | 4 +- dlls/dbghelp/path.c | 146 +++++++++++---------------------- dlls/dbghelp/pe_module.c | 2 +- 4 files changed, 53 insertions(+), 103 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index ae11771f1d9..c6d144bb175 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -401,8 +401,6 @@ 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 */ - DMT_PDB, /* .PDB file */ - DMT_DBG, /* .DBG file */ };
struct process; @@ -775,7 +773,7 @@ extern DWORD pdb_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW*
/* path.c */ extern BOOL path_find_symbol_file(const struct process* pcs, const struct module* module, - PCSTR full_path, enum module_type type, const GUID* guid, DWORD dw1, DWORD dw2, + PCSTR full_path, BOOL is_pdb, const GUID* guid, DWORD dw1, DWORD dw2, WCHAR *buffer, BOOL* is_unmatched) DECLSPEC_HIDDEN; extern WCHAR *get_dos_file_name(const WCHAR *filename) __WINE_DEALLOC(HeapFree, 3) __WINE_MALLOC DECLSPEC_HIDDEN; extern BOOL search_dll_path(const struct process* process, const WCHAR *name, WORD machine, diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 6af3b415bf8..5e699d54e2c 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3317,11 +3317,11 @@ static HANDLE map_pdb_file(const struct process* pcs, switch (lookup->kind) { case PDB_JG: - ret = path_find_symbol_file(pcs, module, lookup->filename, DMT_PDB, NULL, lookup->timestamp, + ret = path_find_symbol_file(pcs, module, lookup->filename, TRUE, NULL, lookup->timestamp, lookup->age, dbg_file_path, &module->module.PdbUnmatched); break; case PDB_DS: - ret = path_find_symbol_file(pcs, module, lookup->filename, DMT_PDB, &lookup->guid, 0, + ret = path_find_symbol_file(pcs, module, lookup->filename, TRUE, &lookup->guid, 0, lookup->age, dbg_file_path, &module->module.PdbUnmatched); break; } diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index dce700b34e7..2437a7b6131 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -461,13 +461,12 @@ BOOL WINAPI SymFindFileInPath(HANDLE hProcess, PCSTR searchPath, PCSTR full_path
struct module_find { - enum module_type kind; - /* pe: dw1 DWORD:timestamp - * dw2 size of image (from PE header) - * pdb: guid PDB guid (if DS PDB file) + BOOL is_pdb; + /* pdb: guid PDB guid (if DS PDB file) * or dw1 PDB timestamp (if JG PDB file) * dw2 PDB age - * elf: dw1 DWORD:CRC 32 of ELF image (Wine only) + * dbg: dw1 DWORD:timestamp + * dw2 size of image (from PE header) */ const GUID* guid; DWORD dw1; @@ -484,7 +483,7 @@ struct module_find static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) { struct module_find* mf = user; - DWORD size, timestamp; + DWORD timestamp; unsigned matched = 0;
/* the matching weights: @@ -492,107 +491,60 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) * +1 if first parameter and second parameter match */
- /* FIXME: should check that id/two match the file pointed - * by buffer - */ - switch (mf->kind) + if (mf->is_pdb) { - case DMT_PE: + struct pdb_lookup pdb_lookup; + char fn[MAX_PATH]; + + WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); + pdb_lookup.filename = fn; + + if (mf->guid) { - HANDLE hFile, hMap; - void* mapping; - - timestamp = ~mf->dw1; - size = ~mf->dw2; - hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) return FALSE; - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) - { - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) - { - IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping); - if (!nth) - { - UnmapViewOfFile(mapping); - CloseHandle(hMap); - CloseHandle(hFile); - return FALSE; - } - matched++; - timestamp = nth->FileHeader.TimeDateStamp; - size = nth->OptionalHeader.SizeOfImage; - UnmapViewOfFile(mapping); - } - CloseHandle(hMap); - } - CloseHandle(hFile); - if (timestamp != mf->dw1) - WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); - if (size != mf->dw2) - WARN("Found %s, but wrong size\n", debugstr_w(buffer)); - if (timestamp == mf->dw1 && size == mf->dw2) matched++; + pdb_lookup.kind = PDB_DS; + pdb_lookup.timestamp = 0; + pdb_lookup.guid = *mf->guid; } - break; - case DMT_PDB: + else { - struct pdb_lookup pdb_lookup; - char fn[MAX_PATH]; - - WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); - pdb_lookup.filename = fn; - - if (mf->guid) - { - pdb_lookup.kind = PDB_DS; - pdb_lookup.timestamp = 0; - pdb_lookup.guid = *mf->guid; - } - else - { - pdb_lookup.kind = PDB_JG; - pdb_lookup.timestamp = mf->dw1; - /* pdb_loopkup.guid = */ - } - pdb_lookup.age = mf->dw2; - - if (!pdb_fetch_file_info(&pdb_lookup, &matched)) return FALSE; + pdb_lookup.kind = PDB_JG; + pdb_lookup.timestamp = mf->dw1; + /* pdb_loopkup.guid = */ } - break; - case DMT_DBG: + pdb_lookup.age = mf->dw2; + + if (!pdb_fetch_file_info(&pdb_lookup, &matched)) return FALSE; + } + else + { + HANDLE hFile, hMap; + void* mapping; + + timestamp = ~mf->dw1; + hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return FALSE; + if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) { - HANDLE hFile, hMap; - void* mapping; - - timestamp = ~mf->dw1; - hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) return FALSE; - if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) + if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { - if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) + const IMAGE_SEPARATE_DEBUG_HEADER* hdr; + hdr = mapping; + + if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) { - const IMAGE_SEPARATE_DEBUG_HEADER* hdr; - hdr = mapping; - - if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) - { - matched++; - timestamp = hdr->TimeDateStamp; - } - UnmapViewOfFile(mapping); + matched++; + timestamp = hdr->TimeDateStamp; } - CloseHandle(hMap); + UnmapViewOfFile(mapping); } - CloseHandle(hFile); - if (timestamp == mf->dw1) matched++; - else WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); + CloseHandle(hMap); } - break; - default: - FIXME("What the heck??\n"); - return FALSE; + CloseHandle(hFile); + if (timestamp == mf->dw1) matched++; + else WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); } + if (matched > mf->matched) { lstrcpyW(mf->filename, buffer); @@ -605,7 +557,7 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) }
BOOL path_find_symbol_file(const struct process* pcs, const struct module* module, - PCSTR full_path, enum module_type type, const GUID* guid, DWORD dw1, DWORD dw2, + PCSTR full_path, BOOL is_pdb, const GUID* guid, DWORD dw1, DWORD dw2, WCHAR *buffer, BOOL* is_unmatched) { struct module_find mf; @@ -624,7 +576,7 @@ BOOL path_find_symbol_file(const struct process* pcs, const struct module* modul
MultiByteToWideChar(CP_ACP, 0, full_path, -1, full_pathW, MAX_PATH); filename = file_name(full_pathW); - mf.kind = type; + mf.is_pdb = is_pdb; *is_unmatched = FALSE;
/* first check full path to file */ diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 77f1aae9283..cd86c363de2 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -550,7 +550,7 @@ static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
TRACE("Processing DBG file %s\n", debugstr_a(dbg_name));
- if (path_find_symbol_file(pcs, module, dbg_name, DMT_DBG, NULL, timestamp, 0, tmp, &module->module.DbgUnmatched) && + if (path_find_symbol_file(pcs, module, dbg_name, FALSE, NULL, timestamp, 0, tmp, &module->module.DbgUnmatched) && (hFile = CreateFileW(tmp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE && ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
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"))
From: Eric Pouech epouech@codeweavers.com
Rely solely on extended module information.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 2 +- dlls/dbghelp/elf_module.c | 5 +---- dlls/dbghelp/module.c | 23 +++++++++++++-------- programs/winedbg/info.c | 37 ++++++++++++++++++++-------------- 4 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index a7ec4bcc426..ac23b0fd6b1 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -717,7 +717,6 @@ extern BOOL macho_read_wine_loader_dbg_info(struct process* pcs, ULONG_P void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN;
/* module.c */ -extern const WCHAR S_ElfW[] DECLSPEC_HIDDEN; extern const WCHAR S_WineLoaderW[] DECLSPEC_HIDDEN; extern const struct loader_ops no_loader_ops DECLSPEC_HIDDEN; extern const struct loader_ops empty_loader_ops DECLSPEC_HIDDEN; @@ -749,6 +748,7 @@ extern BOOL module_remove(struct process* pcs, struct module* module) DECLSPEC_HIDDEN; extern void module_set_module(struct module* module, const WCHAR* name) DECLSPEC_HIDDEN; extern WCHAR* get_wine_loader_name(struct process *pcs) __WINE_DEALLOC(HeapFree, 3) __WINE_MALLOC DECLSPEC_HIDDEN; +extern BOOL module_is_wine_host(const WCHAR* module_name, const WCHAR* ext) DECLSPEC_HIDDEN;
/* msc.c */ extern BOOL pe_load_debug_directory(const struct process* pcs, diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 5ada8c70c9b..303863c773b 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -1082,11 +1082,8 @@ static BOOL elf_load_debug_info_from_map(struct module* module, } lret = dwarf2_parse(module, module->reloc_delta, thunks, fmap); ret = ret || lret; - } - if (wcsstr(module->modulename, S_ElfW) || !wcscmp(module->modulename, S_WineLoaderW)) - { /* add the thunks for native libraries */ - if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) + if (module_is_wine_host(module->modulename, L".so")) elf_new_wine_thunks(module, ht_symtab, thunks); } /* add all the public symbols from symtab */ diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 469f911707a..14ec60bcb89 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -35,7 +35,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
#define NOTE_GNU_BUILD_ID 3
-const WCHAR S_ElfW[] = L"<elf>"; const WCHAR S_WineLoaderW[] = L"<wine-loader>"; static const WCHAR * const ext[] = {L".acm", L".dll", L".drv", L".exe", L".ocx", L".vxd", NULL};
@@ -54,6 +53,20 @@ static int match_ext(const WCHAR* ptr, size_t len) return 0; }
+/* FIXME: implemented from checking on modulename (ie foo.dll.so) + * and Wine loader, but fails to identify unixlib. + * Would require a stronger tagging of ELF modules. + */ +BOOL module_is_wine_host(const WCHAR* module_name, const WCHAR* ext) +{ + size_t len, extlen; + if (!wcscmp(module_name, S_WineLoaderW)) return TRUE; + len = wcslen(module_name); + extlen = wcslen(ext); + return len > extlen && !wcsicmp(&module_name[len - extlen], ext) && + match_ext(module_name, len - extlen); +} + static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr) { const WCHAR* ptr; @@ -101,7 +114,7 @@ static BOOL is_wine_loader(const WCHAR *module) static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) { const WCHAR *ptr, *endptr; - size_t len, l; + size_t len;
endptr = in + lstrlenW(in); endptr -= match_ext(in, endptr - in); @@ -111,12 +124,6 @@ static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) out[len] = '\0'; if (is_wine_loader(out)) lstrcpynW(out, S_WineLoaderW, size); - else - { - if (len > 3 && !wcsicmp(&out[len - 3], L".so") && - (l = match_ext(out, len - 3))) - lstrcpyW(&out[len - l - 3], L"<elf>"); - } while ((*out = towlower(*out))) out++; }
diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index 1fa2076cbd2..aeffd11f3eb 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -131,6 +131,17 @@ struct info_modules unsigned num_used; };
+static const char* get_module_type(const struct info_module* im) +{ + switch (im->ext_module_info.type) + { + case DMT_ELF: return "ELF"; + case DMT_MACHO: return "Mach-O"; + case DMT_PE: return "PE"; + default: return "----"; + } +} + static const char* get_symtype_str(const struct info_module* im) { switch (im->mi.SymType) @@ -181,13 +192,15 @@ static const char* get_machine_str(DWORD machine) static void module_print_info(const struct info_module *module, BOOL is_embedded, BOOL multi_machine) { if (multi_machine) - dbg_printf("%16I64x-%16I64x\t%s\t%-16s%s\n", + dbg_printf("%s%s\t%16I64x-%16I64x\t%s\t%-16s%s\n", + is_embedded ? " \-" : "", get_module_type(module), module->mi.BaseOfImage, module->mi.BaseOfImage + module->mi.ImageSize, get_machine_str(module->mi.MachineType), is_embedded ? "\" : get_symtype_str(module), module->name); else - dbg_printf("%*.*I64x-%*.*I64x\t%-16s%s\n", + dbg_printf("%s%s\t%*.*I64x-%*.*I64x\t%-16s%s\n", + is_embedded ? " \-" : "", get_module_type(module), ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage, ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage + module->mi.ImageSize, is_embedded ? "\" : get_symtype_str(module), module->name); @@ -207,7 +220,9 @@ static int __cdecl module_compare(const void* p1, const void* p2) static inline BOOL module_is_container(const struct info_module *wmod_cntnr, const struct info_module *wmod_child) { - return wmod_cntnr->mi.BaseOfImage <= wmod_child->mi.BaseOfImage && + return (wmod_cntnr->ext_module_info.type == DMT_ELF || wmod_cntnr->ext_module_info.type == DMT_MACHO) && + (wmod_child->ext_module_info.type == DMT_PE) && + wmod_cntnr->mi.BaseOfImage <= wmod_child->mi.BaseOfImage && wmod_cntnr->mi.BaseOfImage + wmod_cntnr->mi.ImageSize >= wmod_child->mi.BaseOfImage + wmod_child->mi.ImageSize; } @@ -289,33 +304,25 @@ void info_win32_module(DWORD64 base, BOOL multi_machine) (base < im.modules[i].mi.BaseOfImage || base >= im.modules[i].mi.BaseOfImage + im.modules[i].mi.ImageSize)) continue; if (!multi_machine && machine != im.modules[i].mi.MachineType) continue; - if (strstr(im.modules[i].name, "<elf>")) + if (im.modules[i].ext_module_info.type == DMT_ELF || im.modules[i].ext_module_info.type == DMT_MACHO) { - dbg_printf("ELF\t"); module_print_info(&im.modules[i], FALSE, multi_machine); /* print all modules embedded in this one */ for (j = 0; j < im.num_used; j++) { - if (!strstr(im.modules[j].name, "<elf>") && module_is_container(&im.modules[i], &im.modules[j])) - { - dbg_printf(" \-PE\t"); + if (module_is_container(&im.modules[i], &im.modules[j])) module_print_info(&im.modules[j], TRUE, multi_machine); - } } } else { /* check module is not embedded in another module */ - for (j = 0; j < im.num_used; j++) + for (j = 0; j < im.num_used; j++) { - if (strstr(im.modules[j].name, "<elf>") && module_is_container(&im.modules[j], &im.modules[i])) + if (module_is_container(&im.modules[j], &im.modules[i])) break; } if (j < im.num_used) continue; - if (strstr(im.modules[i].name, ".so") || strchr(im.modules[i].name, '<')) - dbg_printf("ELF\t"); - else - dbg_printf("PE\t"); module_print_info(&im.modules[i], FALSE, multi_machine); } num_printed++;
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 9 +++++---- dlls/dbghelp/elf_module.c | 5 +++-- dlls/dbghelp/macho_module.c | 3 ++- dlls/dbghelp/minidump.c | 2 +- dlls/dbghelp/module.c | 23 +++++++++++++---------- dlls/dbghelp/pe_module.c | 32 +++++++++++++++++++++++--------- include/wine/dbghelp_ext.h | 2 ++ programs/winedbg/info.c | 8 ++++---- 8 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index ac23b0fd6b1..fcf37d56a30 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -440,8 +440,9 @@ struct module IMAGEHLP_MODULEW64 module; WCHAR modulename[64]; /* used for enumeration */ struct module* next; - enum module_type type : 16; - unsigned short is_virtual : 1; + enum module_type type : 16; + unsigned short is_virtual : 1, + is_wine_builtin : 1; struct cpu* cpu; DWORD64 reloc_delta; WCHAR* real_path; @@ -737,7 +738,7 @@ extern struct module* extern BOOL module_get_debug(struct module_pair*) DECLSPEC_HIDDEN; extern struct module* module_new(struct process* pcs, const WCHAR* name, - enum module_type type, BOOL virtual, + enum module_type type, BOOL builtin, BOOL virtual, DWORD64 addr, DWORD64 size, ULONG_PTR stamp, ULONG_PTR checksum, WORD machine) DECLSPEC_HIDDEN; extern struct module* @@ -779,7 +780,7 @@ extern const WCHAR* file_name(const WCHAR* str) DECLSPEC_HIDDEN; extern const char* file_nameA(const char* str) DECLSPEC_HIDDEN;
/* pe_module.c */ -extern BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth) DECLSPEC_HIDDEN; +extern BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth, BOOL* is_builtin) DECLSPEC_HIDDEN; extern struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, HANDLE hFile, DWORD64 base, DWORD size) DECLSPEC_HIDDEN; diff --git a/dlls/dbghelp/elf_module.c b/dlls/dbghelp/elf_module.c index 303863c773b..00e69d290e2 100644 --- a/dlls/dbghelp/elf_module.c +++ b/dlls/dbghelp/elf_module.c @@ -1083,7 +1083,7 @@ static BOOL elf_load_debug_info_from_map(struct module* module, lret = dwarf2_parse(module, module->reloc_delta, thunks, fmap); ret = ret || lret; /* add the thunks for native libraries */ - if (module_is_wine_host(module->modulename, L".so")) + if (module->is_wine_builtin) elf_new_wine_thunks(module, ht_symtab, thunks); } /* add all the public symbols from symtab */ @@ -1238,7 +1238,8 @@ static BOOL elf_load_file_from_fmap(struct process* pcs, const WCHAR* filename, modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct elf_module_info)); if (!modfmt) return FALSE; - elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE, modbase, + elf_info->module = module_new(pcs, filename, DMT_ELF, + module_is_wine_host(filename, L".so"), FALSE, modbase, fmap->u.elf.elf_size, 0, calc_crc32(fmap->u.elf.handle), elf_get_machine(fmap->u.elf.elfhdr.e_machine)); if (!elf_info->module) diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index b0569593fba..2d831449d39 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -1509,7 +1509,8 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, if (!modfmt) goto leave; if (!load_addr) load_addr = fmap.u.macho.segs_start; - macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr, + macho_info->module = module_new(pcs, filename, DMT_MACHO, module_is_wine_host(filename, L".so"), + FALSE, load_addr, fmap.u.macho.segs_size, 0, calc_crc32(fmap.u.macho.handle), image_get_machine(pcs, load_addr)); if (!macho_info->module) diff --git a/dlls/dbghelp/minidump.c b/dlls/dbghelp/minidump.c index c1b156f1aec..5adbe4fd02d 100644 --- a/dlls/dbghelp/minidump.c +++ b/dlls/dbghelp/minidump.c @@ -235,7 +235,7 @@ static BOOL WINAPI fetch_pe_module_info_cb(PCWSTR name, DWORD64 base, ULONG size
if (!validate_addr64(base)) return FALSE;
- if (pe_load_nt_header(dc->process->handle, base, &nth)) + if (pe_load_nt_header(dc->process->handle, base, &nth, NULL)) add_module(user, name, base, size, nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum, FALSE); diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index 14ec60bcb89..fb0a3bfe977 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -169,13 +169,13 @@ WCHAR *get_wine_loader_name(struct process *pcs) return altname; }
-static const char* get_module_type(enum module_type type, BOOL virtual) +static const char* get_module_type(const struct module* module) { - switch (type) + switch (module->type) { - case DMT_ELF: return virtual ? "Virtual ELF" : "ELF"; - case DMT_PE: return virtual ? "Virtual PE" : "PE"; - case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O"; + case DMT_ELF: return "ELF"; + case DMT_MACHO: return "Mach-O"; + case DMT_PE: return module->is_wine_builtin ? "PE (builtin)" : "PE"; default: return "---"; } } @@ -184,7 +184,7 @@ static const char* get_module_type(enum module_type type, BOOL virtual) * Creates and links a new module to a process */ struct module* module_new(struct process* pcs, const WCHAR* name, - enum module_type type, BOOL virtual, + enum module_type type, BOOL builtin, BOOL virtual, DWORD64 mod_addr, DWORD64 size, ULONG_PTR stamp, ULONG_PTR checksum, WORD machine) { @@ -200,8 +200,8 @@ struct module* module_new(struct process* pcs, const WCHAR* name, module->next = NULL; *pmodule = module;
- TRACE("=> %s %I64x-%I64x %s\n", - get_module_type(type, virtual), mod_addr, mod_addr + size, debugstr_w(name)); + TRACE("=> %s%s%s %I64x-%I64x %s\n", virtual ? "virtual " : "", builtin ? "built-in " : "", + get_module_type(module), mod_addr, mod_addr + size, debugstr_w(name));
pool_init(&module->pool, 65536);
@@ -235,7 +235,8 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
module->reloc_delta = 0; module->type = type; - module->is_virtual = virtual; + module->is_virtual = virtual ? -1 : 0; + module->is_wine_builtin = builtin ? -1 : 0; for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; module->sortlist_valid = FALSE; module->sorttab_size = 0; @@ -948,7 +949,7 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam if (Flags & SLMFLAG_VIRTUAL) { if (!wImageName) return 0; - module = module_new(pcs, wImageName, DMT_PE, TRUE, BaseOfDll, SizeOfDll, 0, 0, IMAGE_FILE_MACHINE_UNKNOWN); + module = module_new(pcs, wImageName, DMT_PE, FALSE, TRUE, BaseOfDll, SizeOfDll, 0, 0, IMAGE_FILE_MACHINE_UNKNOWN); if (!module) return 0; module->module.SymType = SymVirtual; } @@ -1684,6 +1685,8 @@ BOOL WINAPI wine_get_module_information(HANDLE proc, DWORD64 base, struct dhext_ if (!module) return FALSE;
dhmi.type = module->type; + dhmi.is_virtual = module->is_virtual; + dhmi.is_wine_builtin = module->is_wine_builtin; dhmi.debug_format_bitmask = module->debug_format_bitmask; if ((module = module_get_container(pcs, module))) { diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index cd86c363de2..909ac794c38 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -821,7 +821,8 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, if (!base) base = PE_FROM_OPTHDR(&modfmt->u.pe_info->fmap, ImageBase); if (!size) size = PE_FROM_OPTHDR(&modfmt->u.pe_info->fmap, SizeOfImage);
- module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size, + module = module_new(pcs, loaded_name, DMT_PE, modfmt->u.pe_info->fmap.u.pe.builtin, FALSE, + base, size, modfmt->u.pe_info->fmap.u.pe.file_header.TimeDateStamp, PE_FROM_OPTHDR(&modfmt->u.pe_info->fmap, CheckSum), modfmt->u.pe_info->fmap.u.pe.file_header.Machine); @@ -852,15 +853,27 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, * pe_load_nt_header * */ -BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth) +BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth, BOOL* is_builtin) { IMAGE_DOS_HEADER dos;
- return ReadProcessMemory(hProc, (char*)(DWORD_PTR)base, &dos, sizeof(dos), NULL) && - dos.e_magic == IMAGE_DOS_SIGNATURE && - ReadProcessMemory(hProc, (char*)(DWORD_PTR)(base + dos.e_lfanew), - nth, sizeof(*nth), NULL) && - nth->Signature == IMAGE_NT_SIGNATURE; + if (!ReadProcessMemory(hProc, (char*)(DWORD_PTR)base, &dos, sizeof(dos), NULL) || + dos.e_magic != IMAGE_DOS_SIGNATURE || + !ReadProcessMemory(hProc, (char*)(DWORD_PTR)(base + dos.e_lfanew), + nth, sizeof(*nth), NULL) || + nth->Signature != IMAGE_NT_SIGNATURE) + return FALSE; + if (is_builtin) + { + if (dos.e_lfanew >= sizeof(dos) + sizeof(builtin_signature)) + { + char sig[sizeof(builtin_signature)]; + *is_builtin = ReadProcessMemory(hProc, (char*)(DWORD_PTR)base + sizeof(dos), sig, sizeof(sig), NULL) && + !memcmp(sig, builtin_signature, sizeof(builtin_signature)); + } + else *is_builtin = FALSE; + } + return TRUE; }
/****************************************************************** @@ -875,11 +888,12 @@ struct module* pe_load_builtin_module(struct process* pcs, const WCHAR* name, if (base && pcs->dbg_hdr_addr) { IMAGE_NT_HEADERS nth; + BOOL is_builtin;
- if (pe_load_nt_header(pcs->handle, base, &nth)) + if (pe_load_nt_header(pcs->handle, base, &nth, &is_builtin)) { if (!size) size = nth.OptionalHeader.SizeOfImage; - module = module_new(pcs, name, DMT_PE, FALSE, base, size, + module = module_new(pcs, name, DMT_PE, is_builtin, FALSE, base, size, nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum, nth.FileHeader.Machine); diff --git a/include/wine/dbghelp_ext.h b/include/wine/dbghelp_ext.h index 389b0f99fa0..c043019ac59 100644 --- a/include/wine/dbghelp_ext.h +++ b/include/wine/dbghelp_ext.h @@ -44,6 +44,8 @@ enum dhext_debug_format struct dhext_module_information { enum module_type type; + unsigned is_wine_builtin : 1, + is_virtual : 1; unsigned debug_format_bitmask; };
diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index aeffd11f3eb..fa499ba3ffe 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -131,13 +131,13 @@ struct info_modules unsigned num_used; };
-static const char* get_module_type(const struct info_module* im) +static const char* get_module_type(const struct info_module* im, BOOL is_embedded) { switch (im->ext_module_info.type) { case DMT_ELF: return "ELF"; case DMT_MACHO: return "Mach-O"; - case DMT_PE: return "PE"; + case DMT_PE: return !is_embedded && im->ext_module_info.is_wine_builtin ? "PE-Wine" : "PE"; default: return "----"; } } @@ -193,14 +193,14 @@ static void module_print_info(const struct info_module *module, BOOL is_embedded { if (multi_machine) dbg_printf("%s%s\t%16I64x-%16I64x\t%s\t%-16s%s\n", - is_embedded ? " \-" : "", get_module_type(module), + is_embedded ? " \-" : "", get_module_type(module, is_embedded), module->mi.BaseOfImage, module->mi.BaseOfImage + module->mi.ImageSize, get_machine_str(module->mi.MachineType), is_embedded ? "\" : get_symtype_str(module), module->name); else dbg_printf("%s%s\t%*.*I64x-%*.*I64x\t%-16s%s\n", - is_embedded ? " \-" : "", get_module_type(module), + is_embedded ? " \-" : "", get_module_type(module, is_embedded), ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage, ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage + module->mi.ImageSize, is_embedded ? "\" : get_symtype_str(module), module->name);
From: Eric Pouech eric.pouech@gmail.com
On MacOs, starting with Big Sur 11.0.1, the system dynamic libraries are no longer directly accessible on disk. They are still avaible through dlopen and friends. For getting access to the images (and their debug symbol), Apple provides in the developper kit the tools to extract the files. Note that is handled as a database of all system libraries, where ASLR is in place such that segments of a given library are no longer contiguous in memory (dbghelp doesn't currently handle this).
A part from not having image information nor debug information, another side effect is that dbghelp tries every time it refreshes the mach-o module list to reload any library for which it didn't have an image file. This can be lengthy (esp when a typical process has more than 300 modules loaded).
This patch forces the creation of the dbghelp module even if the image file isn't found.
this patch cut startup time of 'winedbg notepad' from 9.9 to 7.4s. YMMV.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 3 ++- dlls/dbghelp/macho_module.c | 45 ++++++++++++++++++++++++++-------- dlls/dbghelp/module.c | 2 ++ include/wine/dbghelp_ext.h | 3 ++- programs/winedbg/info.c | 10 ++++++-- 5 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index fcf37d56a30..0ac1307df96 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -442,7 +442,8 @@ struct module struct module* next; enum module_type type : 16; unsigned short is_virtual : 1, - is_wine_builtin : 1; + is_wine_builtin : 1, + has_file_image : 1; struct cpu* cpu; DWORD64 reloc_delta; WCHAR* real_path; diff --git a/dlls/dbghelp/macho_module.c b/dlls/dbghelp/macho_module.c index 2d831449d39..90c38b557bb 100644 --- a/dlls/dbghelp/macho_module.c +++ b/dlls/dbghelp/macho_module.c @@ -1405,6 +1405,9 @@ static BOOL macho_load_debug_info(struct process *pcs, struct module* module) return FALSE; }
+ if (!module->has_file_image) /* no much more we can do here */ + return FALSE; + ifm = &module->format_info[DFI_MACHO]->u.macho_info->file_map; fmap = &ifm->u.macho;
@@ -1489,17 +1492,22 @@ static void macho_module_remove(struct process* pcs, struct module_format* modfm * TRUE on success */ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, - ULONG_PTR load_addr, struct macho_info* macho_info) + ULONG_PTR load_addr, struct macho_info* macho_info, BOOL with_image) { BOOL ret = TRUE; BOOL split_segs; struct image_file_map fmap;
- TRACE("(%p/%p, %s, 0x%08Ix, %p/0x%08x)\n", pcs, pcs->handle, debugstr_w(filename), - load_addr, macho_info, macho_info->flags); + TRACE("(%p/%p, %s, 0x%08Ix, %p/0x%08x, %u)\n", pcs, pcs->handle, debugstr_w(filename), + load_addr, macho_info, macho_info->flags, with_image);
split_segs = image_uses_split_segs(pcs, load_addr); - if (!macho_map_file(pcs, filename, split_segs, &fmap)) return FALSE; + if (with_image) + { + if (!macho_map_file(pcs, filename, split_segs, &fmap)) return FALSE; + } + else + reset_file_map(&fmap);
if (macho_info->flags & MACHO_INFO_MODULE) { @@ -1507,18 +1515,21 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, struct module_format* modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info)); if (!modfmt) goto leave; - if (!load_addr) + if (!load_addr && with_image) load_addr = fmap.u.macho.segs_start; macho_info->module = module_new(pcs, filename, DMT_MACHO, module_is_wine_host(filename, L".so"), FALSE, load_addr, - fmap.u.macho.segs_size, 0, calc_crc32(fmap.u.macho.handle), + with_image ? fmap.u.macho.segs_size : 1024, + 0, with_image ? calc_crc32(fmap.u.macho.handle) : 0, image_get_machine(pcs, load_addr)); if (!macho_info->module) { HeapFree(GetProcessHeap(), 0, modfmt); goto leave; } - macho_info->module->reloc_delta = macho_info->module->module.BaseOfImage - fmap.u.macho.segs_start; + macho_info->module->reloc_delta = macho_info->module->module.BaseOfImage; + if (with_image) macho_info->module->reloc_delta -= fmap.u.macho.segs_start; + macho_module_info = (void*)(modfmt + 1); macho_info->module->format_info[DFI_MACHO] = modfmt;
@@ -1531,6 +1542,7 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
macho_module_info->file_map = fmap; reset_file_map(&fmap); + if (!with_image) macho_info->module->has_file_image = 0;
macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; macho_info->module->format_info[DFI_MACHO]->u.macho_info->is_loader = 0; @@ -1566,7 +1578,7 @@ struct macho_load_params static BOOL macho_load_file_cb(void *param, HANDLE handle, const WCHAR *filename) { struct macho_load_params *macho_load = param; - return macho_load_file(macho_load->process, filename, macho_load->load_addr, macho_load->macho_info); + return macho_load_file(macho_load->process, filename, macho_load->load_addr, macho_load->macho_info, TRUE); }
/****************************************************************** @@ -1606,7 +1618,7 @@ static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filenam
/* Try the path as given. */ if (!ret) - ret = macho_load_file(pcs, filename, load_addr, macho_info); + ret = macho_load_file(pcs, filename, load_addr, macho_info, TRUE); /* Try DYLD_FALLBACK_LIBRARY_PATH, with just the filename (no directories). */ if (!ret) { @@ -1618,6 +1630,19 @@ static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filenam if (!ret && p == filename) ret = search_dll_path(pcs, filename, IMAGE_FILE_MACHINE_UNKNOWN, macho_load_file_cb, &load_params);
+ if (!ret && load_addr) + { + /* Starting at macos 11.0, the system libraries are no longer present on the file system. + * So, if we cannot find an image by its filename, just declare the module without + * any debug information. + * This avoids, when walking the internal module list, to search each time + * for the module filename. + * Note: doesn't seem to be a simple way to get the size of the loaded Mach-O module + * without the corresponding file image. And it has also ASLR in place, + * where segments of the same module are not contiguous. + */ + ret = macho_load_file(pcs, filename, load_addr, macho_info, FALSE); + } return ret; }
@@ -1908,7 +1933,7 @@ static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_in if (pathW) { MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len); - ret = macho_load_file(pcs, pathW, 0, macho_info); + ret = macho_load_file(pcs, pathW, 0, macho_info, TRUE); HeapFree(GetProcessHeap(), 0, pathW); } } diff --git a/dlls/dbghelp/module.c b/dlls/dbghelp/module.c index fb0a3bfe977..e0b5854532d 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -237,6 +237,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name, module->type = type; module->is_virtual = virtual ? -1 : 0; module->is_wine_builtin = builtin ? -1 : 0; + module->has_file_image = -1; for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; module->sortlist_valid = FALSE; module->sorttab_size = 0; @@ -1687,6 +1688,7 @@ BOOL WINAPI wine_get_module_information(HANDLE proc, DWORD64 base, struct dhext_ dhmi.type = module->type; dhmi.is_virtual = module->is_virtual; dhmi.is_wine_builtin = module->is_wine_builtin; + dhmi.has_file_image = module->has_file_image; dhmi.debug_format_bitmask = module->debug_format_bitmask; if ((module = module_get_container(pcs, module))) { diff --git a/include/wine/dbghelp_ext.h b/include/wine/dbghelp_ext.h index c043019ac59..3cafc49028b 100644 --- a/include/wine/dbghelp_ext.h +++ b/include/wine/dbghelp_ext.h @@ -45,7 +45,8 @@ struct dhext_module_information { enum module_type type; unsigned is_wine_builtin : 1, - is_virtual : 1; + is_virtual : 1, + has_file_image : 1; unsigned debug_format_bitmask; };
diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index fa499ba3ffe..a309af0e778 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -192,15 +192,17 @@ static const char* get_machine_str(DWORD machine) static void module_print_info(const struct info_module *module, BOOL is_embedded, BOOL multi_machine) { if (multi_machine) - dbg_printf("%s%s\t%16I64x-%16I64x\t%s\t%-16s%s\n", + dbg_printf("%s%s%s\t%16I64x-%16I64x\t%s\t%-16s%s\n", is_embedded ? " \-" : "", get_module_type(module, is_embedded), + module->ext_module_info.has_file_image ? "" : "^", module->mi.BaseOfImage, module->mi.BaseOfImage + module->mi.ImageSize, get_machine_str(module->mi.MachineType), is_embedded ? "\" : get_symtype_str(module), module->name); else - dbg_printf("%s%s\t%*.*I64x-%*.*I64x\t%-16s%s\n", + dbg_printf("%s%s%s\t%*.*I64x-%*.*I64x\t%-16s%s\n", is_embedded ? " \-" : "", get_module_type(module, is_embedded), + module->ext_module_info.has_file_image ? "" : "^", ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage, ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage + module->mi.ImageSize, is_embedded ? "\" : get_symtype_str(module), module->name); @@ -262,6 +264,7 @@ void info_win32_module(DWORD64 base, BOOL multi_machine) UINT i, j, num_printed = 0; BOOL opt; DWORD machine; + BOOL has_missing_filename = FALSE;
if (!dbg_curr_process) { @@ -304,6 +307,7 @@ void info_win32_module(DWORD64 base, BOOL multi_machine) (base < im.modules[i].mi.BaseOfImage || base >= im.modules[i].mi.BaseOfImage + im.modules[i].mi.ImageSize)) continue; if (!multi_machine && machine != im.modules[i].mi.MachineType) continue; + if (!im.modules[i].ext_module_info.has_file_image) has_missing_filename = TRUE; if (im.modules[i].ext_module_info.type == DMT_ELF || im.modules[i].ext_module_info.type == DMT_MACHO) { module_print_info(&im.modules[i], FALSE, multi_machine); @@ -331,6 +335,8 @@ void info_win32_module(DWORD64 base, BOOL multi_machine)
if (base && !num_printed) dbg_printf("'0x%0*I64x' is not a valid module address\n", ADDRWIDTH, base); + if (has_missing_filename) + dbg_printf("^ denotes modules for which image file couldn't be found\n"); }
struct class_walker