From: Eric Pouech <epouech@codeweavers.com> Let these helpers work through various configurations, starting with getting thread name from a minidump. Signed-off-by: Eric Pouech <epouech@codeweavers.com> --- programs/winedbg/debugger.h | 4 ++- programs/winedbg/gdbproxy.c | 8 ++--- programs/winedbg/info.c | 53 ++++----------------------------- programs/winedbg/tgt_active.c | 38 ++++++++++++++++++++++- programs/winedbg/tgt_minidump.c | 29 ++++++++++++++++++ programs/winedbg/winedbg.c | 17 +++++++++++ 6 files changed, 94 insertions(+), 55 deletions(-) diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index e778f7eeb95..ff27997c888 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -301,6 +301,7 @@ struct be_process_io BOOL (*read)(HANDLE, const void*, void*, SIZE_T, SIZE_T*); BOOL (*write)(HANDLE, void*, const void*, SIZE_T, SIZE_T*); BOOL (*get_selector)(HANDLE, DWORD, LDT_ENTRY*); + BOOL (*fetch_thread_name)(const struct dbg_thread*, WCHAR**); }; extern struct dbg_process* dbg_curr_process; @@ -395,7 +396,6 @@ extern void info_win32_segments(DWORD start, int length); extern void info_win32_exception(void); extern void info_win32_system(void); extern void info_wine_dbg_channel(BOOL add, const char* chnl, const char* name); -extern WCHAR* fetch_thread_description(DWORD tid); /* memory.c */ extern BOOL memory_read_value(const struct dbg_lvalue* lvalue, DWORD size, void* result); @@ -485,6 +485,7 @@ extern enum dbg_start dbg_active_minidump(int argc, char* argv[]); extern void dbg_active_wait_for_first_exception(void); extern BOOL dbg_attach_debuggee(DWORD pid); extern void fetch_module_name(void* name_addr, void* mod_addr, WCHAR* buffer, size_t bufsz); +extern BOOL dbg_fetch_active_thread_name(DWORD tid, WCHAR **description); /* tgt_minidump.c */ extern void minidump_write(const char*, const EXCEPTION_RECORD*); @@ -531,6 +532,7 @@ extern struct dbg_process* dbg_get_process_h(HANDLE handle); extern void dbg_del_process(struct dbg_process* p); struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid, HANDLE h, void* teb); extern struct dbg_thread* dbg_get_thread(struct dbg_process* p, DWORD tid); +extern WCHAR* dbg_fetch_thread_name(const struct dbg_thread *thread); extern void dbg_del_thread(struct dbg_thread* t); extern BOOL dbg_init(HANDLE hProc, const WCHAR* in, BOOL invade); extern BOOL dbg_load_module(HANDLE hProc, HANDLE hFile, const WCHAR* name, DWORD_PTR base, DWORD size); diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index e937c4edf32..3dbc7f7c32a 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -1801,14 +1801,10 @@ static enum packet_return packet_query_threads(struct gdb_context* gdbctx) reply_buffer_append_str(reply, "id=\""); reply_buffer_append_uinthex(reply, thread->tid, 4); reply_buffer_append_str(reply, "\" name=\""); - if ((description = fetch_thread_description(thread->tid))) + if ((description = dbg_fetch_thread_name(thread))) { reply_buffer_append_wstr(reply, description); - LocalFree(description); - } - else if (strlen(thread->name)) - { - reply_buffer_append_str(reply, thread->name); + free(description); } else { diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c index b5e68763d7f..e1bb33bad53 100644 --- a/programs/winedbg/info.c +++ b/programs/winedbg/info.c @@ -676,39 +676,6 @@ static BOOL get_process_name(DWORD pid, PROCESSENTRY32W* entry) return ret; } -WCHAR* fetch_thread_description(DWORD tid) -{ - static HRESULT (WINAPI *my_GetThreadDescription)(HANDLE, PWSTR*) = NULL; - static BOOL resolved = FALSE; - HANDLE h; - WCHAR* desc = NULL; - - if (!resolved) - { - HMODULE kernelbase = GetModuleHandleA("kernelbase.dll"); - if (kernelbase) - my_GetThreadDescription = (void *)GetProcAddress(kernelbase, "GetThreadDescription"); - resolved = TRUE; - } - - if (!my_GetThreadDescription) - return NULL; - - h = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tid); - if (!h) - return NULL; - - my_GetThreadDescription(h, &desc); - CloseHandle(h); - - if (desc && desc[0] == '\0') - { - LocalFree(desc); - return NULL; - } - return desc; -} - void info_win32_threads(void) { HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); @@ -718,7 +685,6 @@ void info_win32_threads(void) BOOL ok; DWORD lastProcessId = 0; struct dbg_process* p = NULL; - struct dbg_thread* t = NULL; WCHAR *description; entry.dwSize = sizeof(entry); @@ -751,20 +717,13 @@ void info_win32_threads(void) entry.th32OwnerProcessID, p ? " (D)" : "", exename); lastProcessId = entry.th32OwnerProcessID; } - dbg_printf("\t%08lx %4ld%s ", + if (!dbg_fetch_active_thread_name(entry.th32ThreadID, &description)) + description = NULL; + dbg_printf("\t%08lx %4ld%s %ls\n", entry.th32ThreadID, entry.tpBasePri, - (entry.th32ThreadID == dbg_curr_tid) ? " <==" : " "); - - if ((description = fetch_thread_description(entry.th32ThreadID))) - { - dbg_printf("%ls\n", description); - LocalFree(description); - } - else - { - t = dbg_get_thread(p, entry.th32ThreadID); - dbg_printf("%s\n", t ? t->name : ""); - } + (entry.th32ThreadID == dbg_curr_tid) ? " <==" : " ", + description ? description : L""); + free(description); } ok = Thread32Next(snap, &entry); } diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index dba595b5f30..52fae345b98 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -1092,10 +1092,46 @@ static BOOL tgt_process_active_get_selector(HANDLE hThread, DWORD sel, LDT_ENTRY #endif } +BOOL dbg_fetch_active_thread_name(DWORD tid, WCHAR **description) +{ + static HRESULT (WINAPI *my_GetThreadDescription)(HANDLE, PWSTR*) = NULL; + static BOOL resolved = FALSE; + HANDLE h; + WCHAR *result = NULL; + + if (!resolved) + { + HMODULE kernelbase = GetModuleHandleA("kernelbase.dll"); + if (kernelbase) + my_GetThreadDescription = (void *)GetProcAddress(kernelbase, "GetThreadDescription"); + resolved = TRUE; + } + + if (my_GetThreadDescription && (h = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tid))) + { + WCHAR *descr; + if (my_GetThreadDescription(h, &descr) == S_OK) + { + if (*descr) result = wcsdup(descr); + LocalFree(descr); + } + CloseHandle(h); + } + if (!result) return FALSE; + *description = result; + return TRUE; +} + +static BOOL tgt_process_active_fetch_thread_name(const struct dbg_thread *thread, WCHAR **description) +{ + return dbg_fetch_active_thread_name(thread->tid, description); +} + static struct be_process_io be_process_active_io = { tgt_process_active_close_process, tgt_process_active_read, tgt_process_active_write, - tgt_process_active_get_selector + tgt_process_active_get_selector, + tgt_process_active_fetch_thread_name, }; diff --git a/programs/winedbg/tgt_minidump.c b/programs/winedbg/tgt_minidump.c index 87098491392..bed25406e22 100644 --- a/programs/winedbg/tgt_minidump.c +++ b/programs/winedbg/tgt_minidump.c @@ -648,10 +648,39 @@ static BOOL tgt_process_minidump_get_selector(HANDLE hThread, DWORD sel, LDT_ENT return TRUE; } +static BOOL tgt_process_minidump_fetch_thread_name(const struct dbg_thread *thread, WCHAR **description) +{ + struct tgt_process_minidump_data *data = private_data(thread->process); + void *stream; + + if (MiniDumpReadDumpStream(data->mapping, ThreadNamesStream, NULL, &stream, NULL)) + { + MINIDUMP_THREAD_NAME_LIST* mtnl = stream; + ULONG i; + + for (i = 0; i < mtnl->NumberOfThreadNames; i++) + { + if (thread->tid == mtnl->ThreadNames[i].ThreadId) + { + MINIDUMP_STRING *mdmp_string = (MINIDUMP_STRING *)((char*)data->mapping + mtnl->ThreadNames[i].RvaOfThreadName); + WCHAR *ret; + if (!mdmp_string->Length) return FALSE; + if (!(ret = malloc(mdmp_string->Length + sizeof(WCHAR)))) return FALSE; + memcpy(ret, mdmp_string->Buffer, mdmp_string->Length); + ret[mdmp_string->Length / sizeof(WCHAR)] = L'\0'; + *description = ret; + return TRUE; + } + } + } + return FALSE; +} + static struct be_process_io be_process_minidump_io = { tgt_process_minidump_close_process, tgt_process_minidump_read, tgt_process_minidump_write, tgt_process_minidump_get_selector, + tgt_process_minidump_fetch_thread_name, }; diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index c7f14e8238f..6d9afba7a6d 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -513,6 +513,23 @@ void dbg_del_thread(struct dbg_thread* t) free(t); } +WCHAR* dbg_fetch_thread_name(const struct dbg_thread *thread) +{ + WCHAR *descr; + + if (thread->process->process_io->fetch_thread_name && + thread->process->process_io->fetch_thread_name(thread, &descr)) + return descr; + if (*thread->name) + { + DWORD len = MultiByteToWideChar(CP_ACP, 0, thread->name, -1, NULL, 0); + if ((descr = malloc(len * sizeof(WCHAR)))) + MultiByteToWideChar(CP_ACP, 0, thread->name, -1, descr, len); + return descr; + } + return NULL; +} + void dbg_set_option(const char* option, const char* val) { if (!strcasecmp(option, "module_load_mismatched")) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10562