Index: source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h =================================================================== --- source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h +++ source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h @@ -100,6 +100,9 @@ void ReadExceptionRecord(); + void + ReadModuleList(); + // A thin wrapper around WinAPI's MiniDumpReadDumpStream to avoid redundant // checks. If there's a failure (e.g., if the requested stream doesn't exist), // the function returns nullptr and sets *size_out to 0. Index: source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp =================================================================== --- source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp +++ source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp @@ -30,6 +30,7 @@ #include "lldb/Target/UnixSignals.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ConvertUTF.h" #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" #include "ExceptionRecord.h" @@ -37,6 +38,36 @@ using namespace lldb_private; +namespace +{ + +// Getting a string out of a mini dump is a chore. You're usually given a +// relative virtual address (RVA), which points to a counted string that's in +// Windows Unicode (UTF-16). This wrapper handles all the redirection and +// returns a UTF-8 copy of the string. +std::string +GetMiniDumpString(const void *base_addr, const RVA rva) +{ + std::string result; + if (!base_addr) + { + return result; + } + auto md_string = reinterpret_cast(static_cast(base_addr) + rva); + auto source_start = reinterpret_cast(md_string->Buffer); + const auto source_length = ::wcslen(md_string->Buffer); + const auto source_end = source_start + source_length; + result.resize(4*source_length); // worst case length + auto result_start = reinterpret_cast(&result[0]); + const auto result_end = result_start + result.size(); + ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion); + const auto result_size = std::distance(reinterpret_cast(&result[0]), result_start); + result.resize(result_size); // shrink to actual length + return result; +} + +} // anonymous namespace + // Encapsulates the private data for ProcessWinMiniDump. // TODO(amccarth): Determine if we need a mutex for access. class ProcessWinMiniDump::Data @@ -133,8 +164,7 @@ } m_target.SetArchitecture(DetermineArchitecture()); - // TODO(amccarth): Build the module list. - + ReadModuleList(); ReadExceptionRecord(); return error; @@ -341,6 +371,31 @@ } } +void +ProcessWinMiniDump::ReadModuleList() { + size_t size = 0; + auto module_list_ptr = static_cast(FindDumpStream(ModuleListStream, &size)); + if (!module_list_ptr || module_list_ptr->NumberOfModules == 0) + { + return; + } + + for (ULONG32 i = 0; i < module_list_ptr->NumberOfModules; ++i) + { + const auto &module = module_list_ptr->Modules[i]; + const auto file_name = GetMiniDumpString(m_data_up->m_base_addr, module.ModuleNameRva); + ModuleSpec module_spec = FileSpec(file_name, true); + + lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec); + if (!module_sp) + { + continue; + } + bool load_addr_changed = false; + module_sp->SetLoadAddress(GetTarget(), module.BaseOfImage, false, load_addr_changed); + } +} + void * ProcessWinMiniDump::FindDumpStream(unsigned stream_number, size_t *size_out) { void *stream = nullptr;