dbghelp: Don't set ELF loader when wine's loader isn't accessible.

For dbghelp in 32-bit, when accessing a live debuggee in multi-arch
configuration, Wine's ELF loader is likely mapped above 4G, hence
not accessible with 32bit Windows APIs.
So don't try to expose the ELF libraries in that case.
Introducing a new loader operation class to support live targets, for
which system operations are not accessible, but pretending they are
successful.

Note:
- when Wine's loader ELF module isn't registered by dbghelp,
  any other ELF module will not be registered by dbghelp.
- further work may be needed for winedbg in auto mode (launched with
  AeDebug key on process exception) as in that mode winedbg
  doesn't relaunch itself in 64bit, so won't be able to access
  (64bit) ELF information (in multi-arch configuration).

Signed-off-by: Eric Pouech <eric.pouech@gmail.com>
This commit is contained in:
Eric Pouech 2023-03-08 11:43:22 +01:00 committed by Alexandre Julliard
parent 0f98972fe2
commit 9877ba9732
4 changed files with 43 additions and 16 deletions

View file

@ -716,6 +716,7 @@ void minidump_add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size
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;
extern BOOL module_init_pair(struct module_pair* pair, HANDLE hProcess,
DWORD64 addr) DECLSPEC_HIDDEN;

View file

@ -39,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct elf_info
{
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
DWORD_PTR dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
DWORD64 dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */
};
@ -1769,8 +1769,14 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs, ULONG_PTR addr)
HeapFree(GetProcessHeap(), 0, loader);
}
if (!ret || !elf_info.dbg_hdr_addr) return FALSE;
TRACE("Found ELF debug header %#Ix\n", elf_info.dbg_hdr_addr);
if (elf_info.dbg_hdr_addr != (ULONG_PTR)elf_info.dbg_hdr_addr)
{
ERR("Unable to access ELF libraries (outside 32bit limit)\n");
module_remove(pcs, elf_info.module);
pcs->loader = &empty_loader_ops;
return FALSE;
}
TRACE("Found ELF debug header %#I64x\n", elf_info.dbg_hdr_addr);
elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1;
module_set_module(elf_info.module, S_WineLoaderW);
pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr;

View file

@ -1548,11 +1548,6 @@ PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
return module->cpu->find_runtime_function(module, AddrBase);
}
static BOOL native_synchronize_module_list(struct process* pcs)
{
return FALSE;
}
static struct module* native_load_module(struct process* pcs, const WCHAR* name, ULONG_PTR addr)
{
return NULL;
@ -1564,22 +1559,48 @@ static BOOL native_load_debug_info(struct process* process, struct module* modul
return FALSE;
}
static BOOL native_enum_modules(struct process *process, enum_modules_cb cb, void* user)
{
return FALSE;
}
static BOOL native_fetch_file_info(struct process* process, const WCHAR* name, ULONG_PTR load_addr, DWORD_PTR* base,
DWORD* size, DWORD* checksum)
{
return FALSE;
}
static BOOL noloader_synchronize_module_list(struct process* pcs)
{
return FALSE;
}
static BOOL noloader_enum_modules(struct process *process, enum_modules_cb cb, void* user)
{
return FALSE;
}
static BOOL empty_synchronize_module_list(struct process* pcs)
{
return TRUE;
}
static BOOL empty_enum_modules(struct process *process, enum_modules_cb cb, void* user)
{
return TRUE;
}
/* to be used when debuggee isn't a live target */
const struct loader_ops no_loader_ops =
{
native_synchronize_module_list,
noloader_synchronize_module_list,
native_load_module,
native_load_debug_info,
native_enum_modules,
noloader_enum_modules,
native_fetch_file_info,
};
/* to be used when debuggee is a live target, but which system information isn't available */
const struct loader_ops empty_loader_ops =
{
empty_synchronize_module_list,
native_load_module,
native_load_debug_info,
empty_enum_modules,
native_fetch_file_info,
};

View file

@ -735,7 +735,6 @@ static void test_loaded_modules(void)
}
ret = SymRefreshModuleList(pi.hProcess);
todo_wine_if(get_process_kind(pi.hProcess) == PCSKIND_WOW64)
ok(ret || broken(GetLastError() == STATUS_PARTIAL_COPY /* Win11 in some cases */), "SymRefreshModuleList failed: %lu\n", GetLastError());
SymCleanup(pi.hProcess);