1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

dbghelp: Pretend mach-o is present in case of failure.

On MacOs, starting with Big Sur 11.0.1, the system dynamic
libraries are no longer directly accessible on disk.
They are still available 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
this 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).

Apart 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 cuts startup time of 'winedbg notepad' from 9.9 to 7.4s.
YMMV.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
Eric Pouech 2023-11-16 18:38:02 +01:00 committed by Alexandre Julliard
parent 01c98c5eaf
commit 60108ea1bc
5 changed files with 49 additions and 14 deletions

View File

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

View File

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

View File

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

View File

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

View File

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