Allow 64bit dbghelp handle a 32bit target on WOW64 context The good news is that the serie is rather small.
Improvements on last patch are welcomed :-(
A+ ---
Eric Pouech (3): dbghelp: split storage of PE header dbghelp: now storing the IMAGE_OPTIONAL_HEADER in either 32bit or 64bit form dbghelp: fix failing SymInitialize for a live 32bit target from a 64bit caller in WOW64
dlls/dbghelp/dbghelp.c | 58 +++++++++++++++++++++++++++++++++--- dlls/dbghelp/image_private.h | 6 +++- dlls/dbghelp/pe_module.c | 37 ++++++++++++++++------- 3 files changed, 86 insertions(+), 15 deletions(-)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/image_private.h | 3 ++- dlls/dbghelp/pe_module.c | 49 +++++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h index 870f5300575..8d44458b7c9 100644 --- a/dlls/dbghelp/image_private.h +++ b/dlls/dbghelp/image_private.h @@ -150,7 +150,8 @@ struct image_file_map struct pe_file_map { HANDLE hMap; - IMAGE_NT_HEADERS ntheader; + IMAGE_FILE_HEADER file_header; + IMAGE_OPTIONAL_HEADER opt_header; BOOL builtin; unsigned full_count; void* full_map; diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index 5849b33a244..fa4d0766d17 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -75,7 +75,7 @@ static const char* pe_map_section(struct image_section_map* ism) void* mapping; struct pe_file_map* fmap = &ism->fmap->u.pe;
- if (ism->sidx >= 0 && ism->sidx < fmap->ntheader.FileHeader.NumberOfSections && + if (ism->sidx >= 0 && ism->sidx < fmap->file_header.NumberOfSections && fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) { IMAGE_NT_HEADERS* nth; @@ -115,7 +115,7 @@ static BOOL pe_find_section(struct image_file_map* fmap, const char* name, unsigned i; char tmp[IMAGE_SIZEOF_SHORT_NAME + 1];
- for (i = 0; i < fmap->u.pe.ntheader.FileHeader.NumberOfSections; i++) + for (i = 0; i < fmap->u.pe.file_header.NumberOfSections; i++) { sectname = (const char*)fmap->u.pe.sect[i].shdr.Name; /* long section names start with a '/' (at least on MinGW32) */ @@ -147,7 +147,7 @@ static BOOL pe_find_section(struct image_file_map* fmap, const char* name, */ static void pe_unmap_section(struct image_section_map* ism) { - if (ism->sidx >= 0 && ism->sidx < ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections && + if (ism->sidx >= 0 && ism->sidx < ism->fmap->u.pe.file_header.NumberOfSections && ism->fmap->u.pe.sect[ism->sidx].mapped != IMAGE_NO_MAP) { pe_unmap_full(ism->fmap); @@ -162,7 +162,7 @@ static void pe_unmap_section(struct image_section_map* ism) */ static DWORD_PTR pe_get_map_rva(const struct image_section_map* ism) { - if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections) + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.file_header.NumberOfSections) return 0; return ism->fmap->u.pe.sect[ism->sidx].shdr.VirtualAddress; } @@ -174,7 +174,7 @@ static DWORD_PTR pe_get_map_rva(const struct image_section_map* ism) */ static unsigned pe_get_map_size(const struct image_section_map* ism) { - if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.ntheader.FileHeader.NumberOfSections) + if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.pe.file_header.NumberOfSections) return 0; return ism->fmap->u.pe.sect[ism->sidx].shdr.Misc.VirtualSize; } @@ -190,7 +190,7 @@ static void pe_unmap_file(struct image_file_map* fmap) { struct image_section_map ism; ism.fmap = fmap; - for (ism.sidx = 0; ism.sidx < fmap->u.pe.ntheader.FileHeader.NumberOfSections; ism.sidx++) + for (ism.sidx = 0; ism.sidx < fmap->u.pe.file_header.NumberOfSections; ism.sidx++) { pe_unmap_section(&ism); } @@ -258,7 +258,8 @@ BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) unsigned i;
if (!(nthdr = RtlImageNtHeader(mapping))) goto error; - memcpy(&fmap->u.pe.ntheader, nthdr, sizeof(fmap->u.pe.ntheader)); + memcpy(&fmap->u.pe.file_header, &nthdr->FileHeader, sizeof(fmap->u.pe.file_header)); + memcpy(&fmap->u.pe.opt_header, &nthdr->OptionalHeader, sizeof(fmap->u.pe.opt_header)); switch (nthdr->OptionalHeader.Magic) { case 0x10b: fmap->addr_size = 32; break; @@ -298,8 +299,8 @@ BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) { WARN("Bad coff table... wipping out\n"); /* we have bad information here, wipe it out */ - fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable = 0; - fmap->u.pe.ntheader.FileHeader.NumberOfSymbols = 0; + fmap->u.pe.file_header.PointerToSymbolTable = 0; + fmap->u.pe.file_header.NumberOfSymbols = 0; fmap->u.pe.strtable = NULL; } } @@ -362,16 +363,16 @@ static BOOL pe_locate_with_coff_symbol_table(struct module* module) struct symt_data* sym; const char* mapping;
- numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols; - if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym) + numsym = fmap->u.pe.file_header.NumberOfSymbols; + if (!fmap->u.pe.file_header.PointerToSymbolTable || !numsym) return TRUE; if (!(mapping = pe_map_full(fmap, NULL))) return FALSE; - isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable); + isym = (const IMAGE_SYMBOL*)(mapping + fmap->u.pe.file_header.PointerToSymbolTable);
for (i = 0; i < numsym; i+= naux, isym += naux) { if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && - isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections) + isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.file_header.NumberOfSections) { if (isym->N.Name.Short) { @@ -424,11 +425,11 @@ static BOOL pe_load_coff_symbol_table(struct module* module) const IMAGE_SECTION_HEADER* sect; const char* mapping;
- numsym = fmap->u.pe.ntheader.FileHeader.NumberOfSymbols; - if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym) + numsym = fmap->u.pe.file_header.NumberOfSymbols; + if (!fmap->u.pe.file_header.PointerToSymbolTable || !numsym) return TRUE; if (!(mapping = pe_map_full(fmap, NULL))) return FALSE; - isym = (const IMAGE_SYMBOL*)((const char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable); + isym = (const IMAGE_SYMBOL*)((const char*)mapping + fmap->u.pe.file_header.PointerToSymbolTable); /* FIXME: no way to get strtable size */ strtable = (const char*)&isym[numsym]; sect = IMAGE_FIRST_SECTION(RtlImageNtHeader((HMODULE)mapping)); @@ -441,7 +442,7 @@ static BOOL pe_load_coff_symbol_table(struct module* module) compiland = NULL; } if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && - isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.ntheader.FileHeader.NumberOfSections) + isym->SectionNumber > 0 && isym->SectionNumber <= fmap->u.pe.file_header.NumberOfSections) { if (isym->N.Name.Short) { @@ -496,7 +497,7 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module) if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP) { ret = stabs_parse(module, - module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase, + module->module.BaseOfImage - fmap->u.pe.opt_header.ImageBase, stab, image_get_map_size(§_stabs) / sizeof(struct stab_nlist), sizeof(struct stab_nlist), stabstr, image_get_map_size(§_stabstr), NULL, NULL); @@ -522,7 +523,7 @@ static BOOL pe_load_dwarf(struct module* module) BOOL ret;
ret = dwarf2_parse(module, - module->module.BaseOfImage - fmap->u.pe.ntheader.OptionalHeader.ImageBase, + module->module.BaseOfImage - fmap->u.pe.opt_header.ImageBase, NULL, /* FIXME: some thunks to deal with ? */ fmap); TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load"); @@ -792,12 +793,12 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, image_unmap_file(&modfmt->u.pe_info->fmap); modfmt->u.pe_info->fmap = builtin.fmap; } - if (!base) base = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.ImageBase; - if (!size) size = modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.SizeOfImage; + if (!base) base = modfmt->u.pe_info->fmap.u.pe.opt_header.ImageBase; + if (!size) size = modfmt->u.pe_info->fmap.u.pe.opt_header.SizeOfImage;
module = module_new(pcs, loaded_name, DMT_PE, FALSE, base, size, - modfmt->u.pe_info->fmap.u.pe.ntheader.FileHeader.TimeDateStamp, - modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.CheckSum); + modfmt->u.pe_info->fmap.u.pe.file_header.TimeDateStamp, + modfmt->u.pe_info->fmap.u.pe.opt_header.CheckSum); if (module) { module->real_path = builtin.path; @@ -810,7 +811,7 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, module->module.SymType = SymDeferred; else pe_load_debug_info(pcs, module); - module->reloc_delta = base - modfmt->u.pe_info->fmap.u.pe.ntheader.OptionalHeader.ImageBase; + module->reloc_delta = base - modfmt->u.pe_info->fmap.u.pe.opt_header.ImageBase; } else {
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/image_private.h | 6 +++++- dlls/dbghelp/pe_module.c | 37 +++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/dlls/dbghelp/image_private.h b/dlls/dbghelp/image_private.h index 8d44458b7c9..83442ffb9e1 100644 --- a/dlls/dbghelp/image_private.h +++ b/dlls/dbghelp/image_private.h @@ -151,7 +151,11 @@ struct image_file_map { HANDLE hMap; IMAGE_FILE_HEADER file_header; - IMAGE_OPTIONAL_HEADER opt_header; + union + { + IMAGE_OPTIONAL_HEADER32 header32; + IMAGE_OPTIONAL_HEADER64 header64; + } opt; BOOL builtin; unsigned full_count; void* full_map; diff --git a/dlls/dbghelp/pe_module.c b/dlls/dbghelp/pe_module.c index fa4d0766d17..5cef277581a 100644 --- a/dlls/dbghelp/pe_module.c +++ b/dlls/dbghelp/pe_module.c @@ -65,6 +65,11 @@ static void pe_unmap_full(struct image_file_map* fmap) } }
+/* as we store either IMAGE_OPTIONAL_HEADER(32|64) inside pe_file_map, + * this helper will read to any field 'field' inside such an header + */ +#define PE_FROM_OPTHDR(fmap, field) (((fmap)->addr_size == 32) ? ((fmap)->u.pe.opt.header32. field) : ((fmap)->u.pe.opt.header64. field)) + /****************************************************************** * pe_map_section * @@ -259,12 +264,24 @@ BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt)
if (!(nthdr = RtlImageNtHeader(mapping))) goto error; memcpy(&fmap->u.pe.file_header, &nthdr->FileHeader, sizeof(fmap->u.pe.file_header)); - memcpy(&fmap->u.pe.opt_header, &nthdr->OptionalHeader, sizeof(fmap->u.pe.opt_header)); switch (nthdr->OptionalHeader.Magic) { - case 0x10b: fmap->addr_size = 32; break; - case 0x20b: fmap->addr_size = 64; break; - default: return FALSE; + case 0x10b: + if (sizeof(void*) == 8 && !(SymGetOptions() & SYMOPT_INCLUDE_32BIT_MODULES)) + { + TRACE("Won't load 32bit module in 64bit dbghelp when options don't ask for it\n"); + goto error; + } + fmap->addr_size = 32; + memcpy(&fmap->u.pe.opt.header32, &nthdr->OptionalHeader, sizeof(fmap->u.pe.opt.header32)); + break; + case 0x20b: + if (sizeof(void*) == 4) return FALSE; + fmap->addr_size = 64; + memcpy(&fmap->u.pe.opt.header64, &nthdr->OptionalHeader, sizeof(fmap->u.pe.opt.header64)); + break; + default: + return FALSE; }
fmap->u.pe.builtin = !memcmp((const IMAGE_DOS_HEADER*)mapping + 1, builtin_signature, sizeof(builtin_signature)); @@ -497,7 +514,7 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module) if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP) { ret = stabs_parse(module, - module->module.BaseOfImage - fmap->u.pe.opt_header.ImageBase, + module->module.BaseOfImage - PE_FROM_OPTHDR(fmap, ImageBase), stab, image_get_map_size(§_stabs) / sizeof(struct stab_nlist), sizeof(struct stab_nlist), stabstr, image_get_map_size(§_stabstr), NULL, NULL); @@ -523,7 +540,7 @@ static BOOL pe_load_dwarf(struct module* module) BOOL ret;
ret = dwarf2_parse(module, - module->module.BaseOfImage - fmap->u.pe.opt_header.ImageBase, + module->module.BaseOfImage - PE_FROM_OPTHDR(fmap, ImageBase), NULL, /* FIXME: some thunks to deal with ? */ fmap); TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load"); @@ -793,12 +810,12 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, image_unmap_file(&modfmt->u.pe_info->fmap); modfmt->u.pe_info->fmap = builtin.fmap; } - if (!base) base = modfmt->u.pe_info->fmap.u.pe.opt_header.ImageBase; - if (!size) size = modfmt->u.pe_info->fmap.u.pe.opt_header.SizeOfImage; + 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, modfmt->u.pe_info->fmap.u.pe.file_header.TimeDateStamp, - modfmt->u.pe_info->fmap.u.pe.opt_header.CheckSum); + PE_FROM_OPTHDR(&modfmt->u.pe_info->fmap, CheckSum)); if (module) { module->real_path = builtin.path; @@ -811,7 +828,7 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name, module->module.SymType = SymDeferred; else pe_load_debug_info(pcs, module); - module->reloc_delta = base - modfmt->u.pe_info->fmap.u.pe.opt_header.ImageBase; + module->reloc_delta = base - PE_FROM_OPTHDR(&modfmt->u.pe_info->fmap, ImageBase); } else {
When: - caller of dbghelp is a 64bit process, - invoking SymInitialize on a 32bit live target running under WOW64
SymInitialize fails because: - check_live_target() erroneously reads the 64bit PEB of the target, while it actually wants the 32bit PEB. - as the ELF base header address isn't set (hidden in CloudFileFlags) in the 64bit PEB, hence causing the failure
So ensure that check_live_target() actually reads the 32bit PEB when handling a 32bit process.
----
I couldn't find a simpler way to fix it :-( (offsetting PEB address by 0x1000 works but is way too hacky)
And I'm still not happy with the result. Is there a better way to solve this?
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index 00d7b61fbd8..9475e2dc2ac 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -27,6 +27,7 @@ #include "wine/debug.h" #include "wdbgexts.h" #include "winnls.h" +#include <tlhelp32.h>
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
@@ -282,11 +283,51 @@ const WCHAR *process_getenv(const struct process *process, const WCHAR *name) return NULL; }
+/* retrieves the PEB32 address of a 32bit target under wow64 when dbghelp is a 64bit process */ +static PEB* get_peb32_addr(HANDLE proc) +{ + HANDLE snap; + HANDLE thread; + THREADENTRY32 te; + PEB* ret = NULL; + DWORD pid = GetProcessId(proc); + THREAD_BASIC_INFORMATION thread_info; + TEB teb; + TEB32 teb32; + SIZE_T res; + + snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (snap == INVALID_HANDLE_VALUE) return NULL; + + te.dwSize = sizeof(te); + if (Thread32First(snap, &te)) + { + do + { + if (te.th32OwnerProcessID == pid && + te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID) && + (thread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, te.th32ThreadID)) != NULL) + { + if (NtQueryInformationThread(thread, ThreadBasicInformation, &thread_info, sizeof(thread_info), NULL) == 0 && + ReadProcessMemory(proc, thread_info.TebBaseAddress, &teb, sizeof(teb), &res ) && + ReadProcessMemory(proc, teb.Tib.ExceptionList, &teb32, sizeof(teb32), &res)) + { + ret = (PEB*)(ULONG_PTR)teb32.Peb; + } + CloseHandle(thread); + } + te.dwSize = sizeof(te); + } while (!ret && Thread32Next(snap, &te)); + } + CloseHandle(snap); + return ret; +} + /****************************************************************** * check_live_target * */ -static BOOL check_live_target(struct process* pcs) +static BOOL check_live_target(struct process* pcs, BOOL wow64, BOOL child_wow64) { PROCESS_BASIC_INFORMATION pbi; ULONG_PTR base = 0, env = 0; @@ -300,11 +341,20 @@ static BOOL check_live_target(struct process* pcs)
if (!pcs->is_64bit) { + void* peb32_addr; DWORD env32; PEB32 peb32; + C_ASSERT(sizeof(void*) != 4 || FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment) == 0x48); - if (!ReadProcessMemory(pcs->handle, pbi.PebBaseAddress, &peb32, sizeof(peb32), NULL)) return FALSE; - if (!ReadProcessMemory(pcs->handle, (char *)pbi.PebBaseAddress + 0x460 /* CloudFileFlags */, &base, sizeof(base), NULL)) return FALSE; + if (!wow64 && child_wow64) + { + peb32_addr = get_peb32_addr(pcs->handle); + if (!peb32_addr) return FALSE; + } + else + peb32_addr = pbi.PebBaseAddress; + if (!ReadProcessMemory(pcs->handle, peb32_addr, &peb32, sizeof(peb32), NULL)) return FALSE; + if (!ReadProcessMemory(pcs->handle, (char *)peb32_addr + 0x460 /* CloudFileFlags */, &base, sizeof(base), NULL)) return FALSE; if (read_process_memory(pcs, peb32.ProcessParameters + 0x48, &env32, sizeof(env32))) env = env32; } else @@ -454,7 +504,7 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP pcs->next = process_first; process_first = pcs;
- if (check_live_target(pcs)) + if (check_live_target(pcs, wow64, child_wow64)) { if (fInvadeProcess) EnumerateLoadedModulesW64(hProcess, process_invade_cb, hProcess);
Eric Pouech eric.pouech@gmail.com writes:
When:
- caller of dbghelp is a 64bit process,
- invoking SymInitialize on a 32bit live target running under WOW64
SymInitialize fails because:
- check_live_target() erroneously reads the 64bit PEB of the target, while it actually wants the 32bit PEB.
- as the ELF base header address isn't set (hidden in CloudFileFlags) in the 64bit PEB, hence causing the failure
So ensure that check_live_target() actually reads the 32bit PEB when handling a 32bit process.
I couldn't find a simpler way to fix it :-( (offsetting PEB address by 0x1000 works but is way too hacky)
Offsetting by 0x1000 is fine.
But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
Offsetting by 0x1000 is fine.
But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
ok I'll resend the serie with just offsetting for now.
is there a way to test the new WoW64 arch before it's enabled?
thanks
Eric Pouech eric.pouech@orange.fr writes:
Offsetting by 0x1000 is fine.
But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
ok I'll resend the serie with just offsetting for now.
is there a way to test the new WoW64 arch before it's enabled?
You can try the patch below. Note that you need to apply the ntdll-NtAlertThreadByThreadId series from wine-staging first.
Le 31/08/2021 à 15:32, Alexandre Julliard a écrit :
Eric Pouech eric.pouech@orange.fr writes:
Offsetting by 0x1000 is fine.
But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
ok I'll resend the serie with just offsetting for now.
is there a way to test the new WoW64 arch before it's enabled?
You can try the patch below. Note that you need to apply the ntdll-NtAlertThreadByThreadId series from wine-staging first.
thanks
didn't run into anything dramatic ;-)
no specific issues on dbghelp testing on my side
as I understand the new DLL scheme (for a WOW64 DLL on 64bit cpu)
- wine loader will always be a 64bit ELF
- all ELF required libs will be loaded as 64bit ELF into that process
- PE module will be 32bit PE but with thunks to 64bit code for interaction with ELF DLLs
one of the current interest of winedbg was the ability to show both the PE modules and the ELF modules and debug both
this will open a nice can of worms as it would require multiple CPUs support for the same process :-(
MS debugger has the ability to switch back and forth between the two worlds (ie set CPU), but requires specific command to display a combined (mutli CPU) backtrace
note: your patch doesn't apply cleanly on top of wine-staging/ntdll-NtAlertThreadByThreadId
(some stuff in common on the wine-staging series and the patch ; I hope I got the conflict resolution right)
A+
If the patch requires staging patch sets wouldn’t it make sense to carry the patch in staging for the time being?
On Wed, Sep 1, 2021 at 10:43 AM Eric Pouech eric.pouech@orange.fr wrote:
Le 31/08/2021 à 15:32, Alexandre Julliard a écrit :
Eric Pouech eric.pouech@orange.fr eric.pouech@orange.fr writes:
Offsetting by 0x1000 is fine.
But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
ok I'll resend the serie with just offsetting for now.
is there a way to test the new WoW64 arch before it's enabled?
You can try the patch below. Note that you need to apply the ntdll-NtAlertThreadByThreadId series from wine-staging first.
thanks
didn't run into anything dramatic ;-)
no specific issues on dbghelp testing on my side
as I understand the new DLL scheme (for a WOW64 DLL on 64bit cpu)
wine loader will always be a 64bit ELF
all ELF required libs will be loaded as 64bit ELF into that process
PE module will be 32bit PE but with thunks to 64bit code for interaction
with ELF DLLs
one of the current interest of winedbg was the ability to show both the PE modules and the ELF modules and debug both
this will open a nice can of worms as it would require multiple CPUs support for the same process :-(
MS debugger has the ability to switch back and forth between the two worlds (ie set CPU), but requires specific command to display a combined (mutli CPU) backtrace
note: your patch doesn't apply cleanly on top of wine-staging/ ntdll-NtAlertThreadByThreadId
(some stuff in common on the wine-staging series and the patch ; I hope I got the conflict resolution right)
A+
On 31/08/2021 12:53, Alexandre Julliard wrote:
Eric Pouech eric.pouech@gmail.com writes:
When:
- caller of dbghelp is a 64bit process,
- invoking SymInitialize on a 32bit live target running under WOW64
SymInitialize fails because:
- check_live_target() erroneously reads the 64bit PEB of the target, while it actually wants the 32bit PEB.
- as the ELF base header address isn't set (hidden in CloudFileFlags) in the 64bit PEB, hence causing the failure
So ensure that check_live_target() actually reads the 32bit PEB when handling a 32bit process.
I couldn't find a simpler way to fix it :-( (offsetting PEB address by 0x1000 works but is way too hacky)
Offsetting by 0x1000 is fine.
But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
Sorry for the off topic remark, but is there some brief documentation on how this is going to work posted anywhere? Will it be optional? (i.e. if the host supplies 32-bit libs, wine will still use them).
I'm mainly concerned about it adding too much overhead, mostly for stuff that relies on heavy library usage for performance (probably graphics API related, like 32-bit games)... But maybe I misunderstand the whole thing.
Gabriel Ivăncescu gabrielopcode@gmail.com writes:
On 31/08/2021 12:53, Alexandre Julliard wrote:
Eric Pouech eric.pouech@gmail.com writes:
When:
- caller of dbghelp is a 64bit process,
- invoking SymInitialize on a 32bit live target running under WOW64
SymInitialize fails because:
- check_live_target() erroneously reads the 64bit PEB of the target, while it actually wants the 32bit PEB.
- as the ELF base header address isn't set (hidden in CloudFileFlags) in the 64bit PEB, hence causing the failure
So ensure that check_live_target() actually reads the 32bit PEB when handling a 32bit process.
I couldn't find a simpler way to fix it :-( (offsetting PEB address by 0x1000 works but is way too hacky)
Offsetting by 0x1000 is fine. But I'd say that the ELF data should be stored in the 64-bit PEB. Also note that once the new Wow64 architecture is enabled, all ELF data inside 32-bit processes is going to be 64-bit.
Sorry for the off topic remark, but is there some brief documentation on how this is going to work posted anywhere? Will it be optional? (i.e. if the host supplies 32-bit libs, wine will still use them).
Nothing is defined yet, but I expect there will be some kind of runtime option.