Index: include/lldb/Host/Host.h =================================================================== --- include/lldb/Host/Host.h +++ include/lldb/Host/Host.h @@ -196,6 +196,8 @@ static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info); + static lldb::addr_t GetProcessBaseAddress(lldb::pid_t pid); + static const lldb::UnixSignalsSP &GetUnixSignals(); /// Launch the process specified in launch_info. The monitoring callback in Index: source/Host/common/Host.cpp =================================================================== --- source/Host/common/Host.cpp +++ source/Host/common/Host.cpp @@ -427,6 +427,10 @@ return module_filespec; } +lldb::addr_t Host::GetProcessBaseAddress(lldb::pid_t pid) { + return LLDB_INVALID_ADDRESS; +} + #endif #if !defined(__linux__) Index: source/Host/windows/Host.cpp =================================================================== --- source/Host/windows/Host.cpp +++ source/Host/windows/Host.cpp @@ -170,6 +170,21 @@ return true; } +lldb::addr_t Host::GetProcessBaseAddress(lldb::pid_t pid) { + AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid)); + if (!snapshot.IsValid()) + return LLDB_INVALID_ADDRESS; + + MODULEENTRY32W me; + me.dwSize = sizeof(MODULEENTRY32W); + if (Module32FirstW(snapshot.get(), &me)) { + // The first module is always the EXE or DLL itself. + return (addr_t)me.modBaseAddr; + } + + return LLDB_INVALID_ADDRESS; +} + HostThread Host::StartMonitoringChildProcess( const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, bool monitor_signals) { Index: source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h =================================================================== --- source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h +++ source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h @@ -12,6 +12,8 @@ #include "lldb/Target/DynamicLoader.h" #include "lldb/lldb-forward.h" +#include + namespace lldb_private { class DynamicLoaderWindowsDYLD : public DynamicLoader { @@ -27,6 +29,9 @@ static DynamicLoader *CreateInstance(Process *process, bool force); + void OnLoadModule(lldb::ModuleSP module_sp, lldb::addr_t module_addr); + void OnUnloadModule(lldb::ModuleSP module_sp, lldb::addr_t module_addr); + void DidAttach() override; void DidLaunch() override; Status CanLoadImage() override; @@ -35,6 +40,12 @@ ConstString GetPluginName() override; uint32_t GetPluginVersion() override; + +protected: + lldb::addr_t GetLoadAddress(lldb::ModuleSP executable); + +private: + std::map m_loaded_modules; }; } // namespace lldb_private Index: source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -1,5 +1,4 @@ -//===-- DynamicLoaderWindowsDYLD.cpp --------------------------------*- C++ -//-*-===// +//===-- DynamicLoaderWindowsDYLD.cpp -----------------------------*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,6 +11,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" @@ -61,41 +61,100 @@ return nullptr; } +void DynamicLoaderWindowsDYLD::OnLoadModule(lldb::ModuleSP module_sp, + lldb::addr_t module_addr) { + m_loaded_modules[module_sp] = module_addr; + UpdateLoadedSectionsCommon(module_sp, module_addr, false); +} + +void DynamicLoaderWindowsDYLD::OnUnloadModule(lldb::ModuleSP module_sp, + lldb::addr_t module_addr) { + m_loaded_modules.erase(module_sp); + UnloadSectionsCommon(module_sp); +} + +lldb::addr_t DynamicLoaderWindowsDYLD::GetLoadAddress(ModuleSP executable) { + // First, see if the load address is already cached. + auto it = m_loaded_modules.find(executable); + if (it != m_loaded_modules.end() && it->second != LLDB_INVALID_ADDRESS) + return it->second; + + lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; + + // Second, try to get it through the process plugins. For a remote process, + // the remote platform will be responsible for providing it. + FileSpec file_spec(executable->GetPlatformFileSpec()); + bool is_loaded = false; + Status status = + m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); + // Servers other than lldb server could respond with a bogus address. + if (status.Success() && is_loaded && load_addr != LLDB_INVALID_ADDRESS) { + m_loaded_modules[executable] = load_addr; + return load_addr; + } + + // Third, try through the underlying platform for a host process. This + // could happen for the NativeProcessFactory. + if (m_process->GetTarget().GetPlatform()->IsHost()) { + load_addr = Host::GetProcessBaseAddress(m_process->GetID()); + if (load_addr != LLDB_INVALID_ADDRESS) { + m_loaded_modules[executable] = load_addr; + return load_addr; + } + } + + return LLDB_INVALID_ADDRESS; +} + void DynamicLoaderWindowsDYLD::DidAttach() { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); ModuleSP executable = GetTargetExecutable(); - if (!executable.get()) return; - // Try to fetch the load address of the file from the process, since there - // could be randomization of the load address. - - // It might happen that the remote has a different dir for the file, so we - // only send the basename of the executable in the query. I think this is safe - // because I doubt that two executables with the same basenames are loaded in - // memory... - FileSpec file_spec( - executable->GetPlatformFileSpec().GetFilename().GetCString()); - bool is_loaded; - addr_t base_addr = 0; - lldb::addr_t load_addr; - Status error = m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); - if (error.Success() && is_loaded) { - base_addr = load_addr; - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, base_addr, false); - } + lldb::addr_t load_addr = GetLoadAddress(executable); + if (load_addr == LLDB_INVALID_ADDRESS) + return; - ModuleList module_list; - module_list.Append(executable); - m_process->GetTarget().ModulesDidLoad(module_list); - m_process->LoadModules(); + // Request the process base. + lldb::addr_t image_base = m_process->GetImageInfoAddress(); + + // Note that the plugin might provide a default base, for example, + // the image base in PECOFF other than the virtual load address. Rebase the + // process's modules if there is a mismatch. + if (image_base != load_addr) { + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); + + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); + m_process->LoadModules(); + } } -void DynamicLoaderWindowsDYLD::DidLaunch() {} +void DynamicLoaderWindowsDYLD::DidLaunch() { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); + + ModuleSP executable = GetTargetExecutable(); + if (!executable.get()) + return; + + lldb::addr_t load_addr = GetLoadAddress(executable); + if (load_addr != LLDB_INVALID_ADDRESS) { + // Update the loaded sections so that the breakpoints can be resolved. + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); + + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); + m_process->LoadModules(); + } +} Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); } Index: source/Plugins/Process/Windows/Common/ProcessWindows.h =================================================================== --- source/Plugins/Process/Windows/Common/ProcessWindows.h +++ source/Plugins/Process/Windows/Common/ProcessWindows.h @@ -90,6 +90,8 @@ lldb::addr_t GetImageInfoAddress() override; + DynamicLoader *GetDynamicLoader() override; + // IDebugDelegate overrides. void OnExitProcess(uint32_t exit_code) override; void OnDebuggerConnected(lldb::addr_t image_base) override; @@ -115,6 +117,6 @@ llvm::sys::Mutex m_mutex; std::unique_ptr m_session_data; }; -} +} // namespace lldb_private #endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ Index: source/Plugins/Process/Windows/Common/ProcessWindows.cpp =================================================================== --- source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -37,6 +37,7 @@ #include "ExceptionRecord.h" #include "ForwardDecl.h" #include "LocalDebugDelegate.h" +#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" #include "ProcessWindowsLog.h" #include "TargetThreadWindows.h" @@ -864,6 +865,13 @@ return LLDB_INVALID_ADDRESS; } +DynamicLoader *ProcessWindows::GetDynamicLoader() { + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin( + this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); + return m_dyld_ap.get(); +} + void ProcessWindows::OnExitProcess(uint32_t exit_code) { // No need to acquire the lock since m_session_data isn't accessed. Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); @@ -880,9 +888,9 @@ SetProcessExitStatus(GetID(), true, 0, exit_code); SetPrivateState(eStateExited); - // If the process exits before any initial stop then notify the debugger + // If the process exits before any initial stop then notify the debugger // of the error otherwise WaitForDebuggerConnection() will be blocked. - // An example of this issue is when a process fails to load a dependent DLL. + // An example of this issue is when a process fails to load a dependent DLL. if (m_session_data && !m_session_data->m_initial_stop_received) { Status error(exit_code, eErrorTypeWin32); OnDebuggerError(error, 0); @@ -916,12 +924,9 @@ GetTarget().SetExecutableModule(module, eLoadDependentsNo); } - bool load_addr_changed; - module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); + auto dyld = static_cast(GetDynamicLoader()); + assert(dyld); + dyld->OnLoadModule(module, image_base); // Add the main executable module to the list of pending module loads. We // can't call GetTarget().ModulesDidLoad() here because we still haven't @@ -1032,12 +1037,11 @@ // return a corresponding ModuleSP. Status error; ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); - bool load_addr_changed = false; - module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); + if (error.Success()) { + auto dyld = static_cast(GetDynamicLoader()); + assert(dyld); + dyld->OnLoadModule(module, module_addr); + } } void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) { @@ -1045,9 +1049,9 @@ if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) { ModuleSP module = resolved_addr.GetModule(); if (module) { - ModuleList unloaded_modules; - unloaded_modules.Append(module); - GetTarget().ModulesDidUnload(unloaded_modules, false); + auto dyld = static_cast(GetDynamicLoader()); + assert(dyld); + dyld->OnUnloadModule(module, module_addr); } } }