Implement multi-arch support from Wine's build tree. (and code cleanup, helper introduction...)
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/dbghelp_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 09457db0fff..01163c0e98a 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -695,7 +695,7 @@ extern BOOL pcs_callback(const struct process* pcs, ULONG action, void* extern void* fetch_buffer(struct process* pcs, unsigned size) DECLSPEC_HIDDEN; extern const char* wine_dbgstr_addr(const ADDRESS64* addr) DECLSPEC_HIDDEN; extern struct cpu* cpu_find(DWORD) DECLSPEC_HIDDEN; -extern const WCHAR *process_getenv(const struct process *process, const WCHAR *name); +extern const WCHAR *process_getenv(const struct process *process, const WCHAR *name) DECLSPEC_HIDDEN; extern DWORD calc_crc32(HANDLE handle) DECLSPEC_HIDDEN;
/* elf_module.c */
From: Eric Pouech eric.pouech@gmail.com
- try_match_file() to check if module meets caller requirements.
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/path.c | 55 +++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 37 deletions(-)
diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index 5b4172e4001..903087695aa 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -705,14 +705,24 @@ WCHAR *get_dos_file_name(const WCHAR *filename) return dos_path; }
+static BOOL try_match_file(const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) +{ + HANDLE file = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file != INVALID_HANDLE_VALUE) + { + BOOL ret = match(param, file, name); + CloseHandle(file); + return ret; + } + return FALSE; +} + BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) { const WCHAR *env; WCHAR *p, *end; size_t len, i; - HANDLE file; WCHAR *buf; - BOOL ret;
name = file_name(name);
@@ -733,13 +743,7 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma p = end + lstrlenW(end); *p++ = '\'; lstrcpyW(p, name); - file = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - ret = match(param, file, buf); - CloseHandle(file); - if (ret) goto found; - } + if (try_match_file(buf, match, param)) goto found;
memcpy(end, programsW, sizeof(programsW)); end += ARRAY_SIZE(programsW); @@ -749,13 +753,7 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma p = end + lstrlenW(end); *p++ = '\'; lstrcpyW(p, name); - file = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - ret = match(param, file, buf); - CloseHandle(file); - if (ret) goto found; - } + if (try_match_file(buf, match, param)) goto found;
heap_free(buf); } @@ -771,21 +769,9 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma swprintf(buf, len, L"%s%s\%s", env, so_dir, name); else swprintf(buf, len, L"%s%s\%s", env, pe_dir, name); - file = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - ret = match(param, file, buf); - CloseHandle(file); - if (ret) goto found; - } + if (try_match_file(buf, match, param)) goto found; swprintf(buf, len, L"%s\%s", env, name); - file = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - ret = match(param, file, buf); - CloseHandle(file); - if (ret) goto found; - } + if (try_match_file(buf, match, param)) goto found; heap_free(buf); }
@@ -822,13 +808,8 @@ BOOL search_unix_path(const WCHAR *name, const WCHAR *path, BOOL (*match)(void*, WideCharToMultiByte(CP_UNIXCP, 0, name, -1, buf + len, size - len, NULL, NULL); if ((dos_path = wine_get_dos_file_name(buf))) { - HANDLE file = CreateFileW(dos_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (file != INVALID_HANDLE_VALUE) - { - ret = match(param, file, dos_path); - CloseHandle(file); - if (ret) TRACE("found %s\n", debugstr_w(dos_path)); - } + ret = try_match_file(dos_path, match, param); + if (ret) TRACE("found %s\n", debugstr_w(dos_path)); heap_free(dos_path); if (ret) break; }
From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/dbghelp.c | 10 +++++ dlls/dbghelp/dbghelp_private.h | 1 + dlls/dbghelp/path.c | 67 ++++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 23 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.c b/dlls/dbghelp/dbghelp.c index 32ce7e13865..2facc58585e 100644 --- a/dlls/dbghelp/dbghelp.c +++ b/dlls/dbghelp/dbghelp.c @@ -332,6 +332,16 @@ const WCHAR *process_getenv(const struct process *process, const WCHAR *name) return NULL; }
+const struct cpu* process_get_cpu(const struct process* pcs) +{ + const struct module* m = pcs->lmodules; + + /* main module is the last one in list */ + if (!m) return dbghelp_current_cpu; + while (m->next) m = m->next; + return m->cpu; +} + /****************************************************************** * check_live_target * diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 01163c0e98a..22e9eec8805 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -696,6 +696,7 @@ extern void* fetch_buffer(struct process* pcs, unsigned size) DECLSPEC_HI extern const char* wine_dbgstr_addr(const ADDRESS64* addr) DECLSPEC_HIDDEN; extern struct cpu* cpu_find(DWORD) DECLSPEC_HIDDEN; extern const WCHAR *process_getenv(const struct process *process, const WCHAR *name) DECLSPEC_HIDDEN; +extern const struct cpu* process_get_cpu(const struct process* pcs) DECLSPEC_HIDDEN; extern DWORD calc_crc32(HANDLE handle) DECLSPEC_HIDDEN;
/* elf_module.c */ diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c index 903087695aa..2320c9da5c3 100644 --- a/dlls/dbghelp/path.c +++ b/dlls/dbghelp/path.c @@ -31,22 +31,19 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
-#ifdef __i386__ -static const WCHAR pe_dir[] = L"\i386-windows"; -static const WCHAR so_dir[] = L"\i386-unix"; -#elif defined __x86_64__ -static const WCHAR pe_dir[] = L"\x86_64-windows"; -static const WCHAR so_dir[] = L"\x86_64-unix"; -#elif defined __arm__ -static const WCHAR pe_dir[] = L"\arm-windows"; -static const WCHAR so_dir[] = L"\arm-unix"; -#elif defined __aarch64__ -static const WCHAR pe_dir[] = L"\aarch64-windows"; -static const WCHAR so_dir[] = L"\aarch64-unix"; -#else -static const WCHAR pe_dir[] = L""; -static const WCHAR so_dir[] = L""; -#endif +static const struct machine_dir +{ + DWORD machine; + const WCHAR *pe_dir; + const WCHAR *so_dir; +} + all_machine_dir[] = +{ + {IMAGE_FILE_MACHINE_I386, L"\i386-windows\", L"\i386-unix\"}, + {IMAGE_FILE_MACHINE_AMD64, L"\x86_64-windows\", L"\x86_64-unix\"}, + {IMAGE_FILE_MACHINE_ARMNT, L"\arm-windows\", L"\arm-unix\"}, + {IMAGE_FILE_MACHINE_ARM64, L"\aarch64-windows\", L"\aarch64-unix\"}, +};
static inline BOOL is_sepA(char ch) {return ch == '/' || ch == '\';} static inline BOOL is_sep(WCHAR ch) {return ch == '/' || ch == '\';} @@ -705,6 +702,14 @@ WCHAR *get_dos_file_name(const WCHAR *filename) return dos_path; }
+static inline const WCHAR* get_machine_dir(const struct machine_dir *machine_dir, const WCHAR *name) +{ + WCHAR *ptr; + if ((ptr = wcsrchr(name, L'.')) && !lstrcmpW(ptr, L".so")) + return machine_dir->so_dir; + return machine_dir->pe_dir; +} + static BOOL try_match_file(const WCHAR *name, BOOL (*match)(void*, HANDLE, const WCHAR*), void *param) { HANDLE file = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); @@ -721,18 +726,27 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma { const WCHAR *env; WCHAR *p, *end; - size_t len, i; + size_t len, i, machine_dir_len; WCHAR *buf; + const struct cpu* cpu; + const struct machine_dir* machine_dir;
name = file_name(name);
+ cpu = process_get_cpu(process); + for (machine_dir = all_machine_dir; machine_dir < all_machine_dir + ARRAY_SIZE(all_machine_dir); machine_dir++) + if (machine_dir->machine == cpu->machine) break; + if (machine_dir >= all_machine_dir + ARRAY_SIZE(all_machine_dir)) return FALSE; + machine_dir_len = max(wcslen(machine_dir->pe_dir), wcslen(machine_dir->so_dir)); + if ((env = process_getenv(process, L"WINEBUILDDIR"))) { const WCHAR dllsW[] = { '\','d','l','l','s','\' }; const WCHAR programsW[] = { '\','p','r','o','g','r','a','m','s','\' };
len = lstrlenW(env); - if (!(buf = heap_alloc((len + 8 + 3 * lstrlenW(name)) * sizeof(WCHAR)))) return FALSE; + if (!(buf = heap_alloc((len + ARRAY_SIZE(programsW) + machine_dir_len + + 2 * lstrlenW(name) + 1) * sizeof(WCHAR)))) return FALSE; wcscpy(buf, env); end = buf + len;
@@ -741,6 +755,11 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma if ((p = wcsrchr(end, '.')) && !lstrcmpW(p, L".so")) *p = 0; if ((p = wcsrchr(end, '.')) && !lstrcmpW(p, L".dll")) *p = 0; p = end + lstrlenW(end); + /* try multi-arch first */ + wcscpy(p, get_machine_dir(machine_dir, name)); + wcscpy(p + wcslen(p), name); + if (try_match_file(buf, match, param)) goto found; + /* then old mono-arch */ *p++ = '\'; lstrcpyW(p, name); if (try_match_file(buf, match, param)) goto found; @@ -751,6 +770,11 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma if ((p = wcsrchr(end, '.')) && !lstrcmpW(p, L".so")) *p = 0; if ((p = wcsrchr(end, '.')) && !lstrcmpW(p, L".exe")) *p = 0; p = end + lstrlenW(end); + /* try multi-arch first */ + wcscpy(p, get_machine_dir(machine_dir, name)); + wcscpy(p + wcslen(p), name); + if (try_match_file(buf, match, param)) goto found; + /* then old mono-arch */ *p++ = '\'; lstrcpyW(p, name); if (try_match_file(buf, match, param)) goto found; @@ -763,12 +787,9 @@ BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL (*ma WCHAR env_name[64]; swprintf(env_name, ARRAY_SIZE(env_name), L"WINEDLLDIR%u", i); if (!(env = process_getenv(process, env_name))) return FALSE; - len = wcslen(env) + wcslen(pe_dir) + wcslen(name) + 2; + len = wcslen(env) + machine_dir_len + wcslen(name) + 1; if (!(buf = heap_alloc(len * sizeof(WCHAR)))) return FALSE; - if ((p = wcsrchr(name, '.')) && !lstrcmpW(p, L".so")) - swprintf(buf, len, L"%s%s\%s", env, so_dir, name); - else - swprintf(buf, len, L"%s%s\%s", env, pe_dir, name); + swprintf(buf, len, L"%s%s%s", env, get_machine_dir(machine_dir, name), name); if (try_match_file(buf, match, param)) goto found; swprintf(buf, len, L"%s\%s", env, name); if (try_match_file(buf, match, param)) goto found;