diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 15f91e683f5..acba5faca37 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -441,7 +441,8 @@ struct module struct module* next; enum dhext_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 b86234daf46..b12007d270e 100644 --- a/dlls/dbghelp/module.c +++ b/dlls/dbghelp/module.c @@ -237,6 +237,8 @@ struct module* module_new(struct process* pcs, const WCHAR* name, module->type = type; module->is_virtual = !!virtual; module->is_wine_builtin = !!builtin; + module->has_file_image = TRUE; + for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; module->sortlist_valid = FALSE; module->sorttab_size = 0; @@ -1687,6 +1689,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/dbghelp.h b/include/dbghelp.h index b638447140c..919efb27be0 100644 --- a/include/dbghelp.h +++ b/include/dbghelp.h @@ -1267,7 +1267,8 @@ struct dhext_module_information { enum dhext_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 7491c4bd5fe..d95b286454a 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -191,9 +191,10 @@ static const char* get_machine_str(DWORD machine) static void module_print_info(const struct info_module *module, BOOL is_embedded, BOOL multi_machine) { char buffer[9]; - snprintf(buffer, sizeof(buffer), "%s%s", + snprintf(buffer, sizeof(buffer), "%s%s%s", is_embedded ? " \\-" : "", - get_module_type(module, is_embedded)); + get_module_type(module, is_embedded), + module->ext_module_info.has_file_image ? "" : "^"); if (multi_machine) dbg_printf("%-8s%16I64x-%16I64x %-16s%-16s%s\n", @@ -266,6 +267,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) { @@ -308,6 +310,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); @@ -335,6 +338,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