Module: wine Branch: master Commit: f0d0562881d8e31e4cde32c849b8a5c00475119f URL: https://gitlab.winehq.org/wine/wine/-/commit/f0d0562881d8e31e4cde32c849b8a5c...
Author: Eric Pouech epouech@codeweavers.com Date: Fri Apr 12 12:31:30 2024 +0200
dbghelp: Store thread names in minidump.
Signed-off-by: Eric Pouech epouech@codeweavers.com
---
dlls/dbghelp/minidump.c | 62 ++++++++++++++++++++++++++++++++++++++++++- dlls/dbghelp/tests/minidump.c | 4 +-- 2 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/dlls/dbghelp/minidump.c b/dlls/dbghelp/minidump.c index 5a2b27f7632..054aaee22a9 100644 --- a/dlls/dbghelp/minidump.c +++ b/dlls/dbghelp/minidump.c @@ -771,6 +771,60 @@ static unsigned dump_threads(struct dump_context* dc) return sz; }
+/****************************************************************** + * dump_threads_names + * + * Dumps into File the information about threads's name + */ +static unsigned dump_threads_names(struct dump_context* dc) +{ + MINIDUMP_THREAD_NAME md_thread_name; + MINIDUMP_THREAD_NAME_LIST md_thread_name_list; + unsigned i, sz; + RVA rva_base; + + /* FIXME this could be optimized + * (we use dc->num_threads disk space, could be optimized to the number of threads with name) + */ + + rva_base = dc->rva; + dc->rva += sz = offsetof(MINIDUMP_THREAD_NAME_LIST, ThreadNames[dc->num_threads]); + + md_thread_name_list.NumberOfThreadNames = 0; + + for (i = 0; i < dc->num_threads; i++) + { + HANDLE thread; + WCHAR *thread_name; + + if ((thread = OpenThread(THREAD_ALL_ACCESS, FALSE, dc->threads[i].tid)) != NULL) + { + if (GetThreadDescription(thread, &thread_name)) + { + MINIDUMP_STRING md_string; + + md_thread_name.ThreadId = dc->threads[i].tid; + md_thread_name.RvaOfThreadName = dc->rva; + + md_string.Length = wcslen(thread_name) * sizeof(WCHAR); + append(dc, &md_string.Length, sizeof(md_string.Length)); + append(dc, thread_name, md_string.Length); + + writeat(dc, + rva_base + offsetof(MINIDUMP_THREAD_NAME_LIST, ThreadNames[md_thread_name_list.NumberOfThreadNames]), + &md_thread_name, sizeof(md_thread_name)); + md_thread_name_list.NumberOfThreadNames++; + LocalFree(thread_name); + } + CloseHandle(thread); + } + } + if (!md_thread_name_list.NumberOfThreadNames) return 0; + + writeat(dc, rva_base, &md_thread_name_list.NumberOfThreadNames, sizeof(md_thread_name_list.NumberOfThreadNames)); + return sz; +} + /****************************************************************** * dump_memory_info * @@ -896,7 +950,7 @@ static DWORD CALLBACK write_minidump(void *_args) fetch_modules_info(dc);
/* 1) init */ - nStreams = 6 + (dc->except_param ? 1 : 0) + + nStreams = 7 + (dc->except_param ? 1 : 0) + (dc->user_stream ? dc->user_stream->UserStreamCount : 0);
/* pad the directory size to a multiple of 4 for alignment purposes */ @@ -931,6 +985,12 @@ static DWORD CALLBACK write_minidump(void *_args) writeat(dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir));
+ mdDir.StreamType = ThreadNamesStream; + mdDir.Location.Rva = dc->rva; + if ((mdDir.Location.DataSize = dump_threads_names(dc))) + writeat(dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), + &mdDir, sizeof(mdDir)); + mdDir.StreamType = ModuleListStream; mdDir.Location.Rva = dc->rva; mdDir.Location.DataSize = dump_modules(dc, FALSE); diff --git a/dlls/dbghelp/tests/minidump.c b/dlls/dbghelp/tests/minidump.c index 64fd3e4fb6c..088e44e6d8b 100644 --- a/dlls/dbghelp/tests/minidump.c +++ b/dlls/dbghelp/tests/minidump.c @@ -105,7 +105,7 @@ typedef DWORD64 stream_mask_t; STREAM2MASK(ProcessVmCountersStream)) /* streams added in Win8 & Win10... */ #define BASIC_STREAM_BROKEN_MASK (STREAM2MASK(SystemMemoryInfoStream) | STREAM2MASK(ProcessVmCountersStream)) -#define BASIC_STREAM_TODO_MASK (STREAM2MASK(SystemMemoryInfoStream) | STREAM2MASK(ProcessVmCountersStream) | STREAM2MASK(ThreadNamesStream)) +#define BASIC_STREAM_TODO_MASK (STREAM2MASK(SystemMemoryInfoStream) | STREAM2MASK(ProcessVmCountersStream)) static void test_minidump_contents(void) { static const struct minidump_streams @@ -234,9 +234,7 @@ static void minidump_check_threads_name(void *data, DWORD tid, const WCHAR* name if (!pSetThreadDescription) return;
ret = MiniDumpReadDumpStream(data, ThreadNamesStream, NULL, (void**)&thread_name_list, &stream_size); - todo_wine ok(ret && thread_name_list, "Couldn't find thread-name-list stream\n"); - if (!ret) return; /* temp */ ok(stream_size == sizeof(thread_name_list->NumberOfThreadNames) + thread_name_list->NumberOfThreadNames * sizeof(thread_name_list->ThreadNames[0]), "Unexpected size\n"); for (i = 0; i < thread_name_list->NumberOfThreadNames; i++)