1 //===-- DynamicLoaderWindowsDYLD.cpp --------------------------------*- C++ 2 //-*-===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "DynamicLoaderWindowsDYLD.h" 11 12 #include "lldb/Core/Module.h" 13 #include "lldb/Core/PluginManager.h" 14 #include "lldb/Target/ExecutionContext.h" 15 #include "lldb/Target/Platform.h" 16 #include "lldb/Target/Process.h" 17 #include "lldb/Target/RegisterContext.h" 18 #include "lldb/Target/Target.h" 19 #include "lldb/Target/ThreadPlanStepInstruction.h" 20 #include "lldb/Utility/Log.h" 21 22 #include "llvm/ADT/Triple.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process) 28 : DynamicLoader(process) {} 29 30 DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {} 31 32 void DynamicLoaderWindowsDYLD::Initialize() { 33 PluginManager::RegisterPlugin(GetPluginNameStatic(), 34 GetPluginDescriptionStatic(), CreateInstance); 35 } 36 37 void DynamicLoaderWindowsDYLD::Terminate() {} 38 39 ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() { 40 static ConstString g_plugin_name("windows-dyld"); 41 return g_plugin_name; 42 } 43 44 const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() { 45 return "Dynamic loader plug-in that watches for shared library " 46 "loads/unloads in Windows processes."; 47 } 48 49 DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, 50 bool force) { 51 bool should_create = force; 52 if (!should_create) { 53 const llvm::Triple &triple_ref = 54 process->GetTarget().GetArchitecture().GetTriple(); 55 if (triple_ref.getOS() == llvm::Triple::Win32) 56 should_create = true; 57 } 58 59 if (should_create) 60 return new DynamicLoaderWindowsDYLD(process); 61 62 return nullptr; 63 } 64 65 void DynamicLoaderWindowsDYLD::OnLoadModule(lldb::ModuleSP module_sp, 66 const ModuleSpec module_spec, 67 lldb::addr_t module_addr) { 68 69 // Resolve the module unless we already have one. 70 if (!module_sp) { 71 Status error; 72 module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, 73 true /* notify */, &error); 74 if (error.Fail()) 75 return; 76 } 77 78 m_loaded_modules[module_sp] = module_addr; 79 UpdateLoadedSectionsCommon(module_sp, module_addr, false); 80 ModuleList module_list; 81 module_list.Append(module_sp); 82 m_process->GetTarget().ModulesDidLoad(module_list); 83 } 84 85 void DynamicLoaderWindowsDYLD::OnUnloadModule(lldb::addr_t module_addr) { 86 Address resolved_addr; 87 if (!m_process->GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) 88 return; 89 90 ModuleSP module_sp = resolved_addr.GetModule(); 91 if (module_sp) { 92 m_loaded_modules.erase(module_sp); 93 UnloadSectionsCommon(module_sp); 94 ModuleList module_list; 95 module_list.Append(module_sp); 96 m_process->GetTarget().ModulesDidUnload(module_list, false); 97 } 98 } 99 100 lldb::addr_t DynamicLoaderWindowsDYLD::GetLoadAddress(ModuleSP executable) { 101 // First, see if the load address is already cached. 102 auto it = m_loaded_modules.find(executable); 103 if (it != m_loaded_modules.end() && it->second != LLDB_INVALID_ADDRESS) 104 return it->second; 105 106 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 107 108 // Second, try to get it through the process plugins. For a remote process, 109 // the remote platform will be responsible for providing it. 110 FileSpec file_spec(executable->GetPlatformFileSpec()); 111 bool is_loaded = false; 112 Status status = 113 m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); 114 // Servers other than lldb server could respond with a bogus address. 115 if (status.Success() && is_loaded && load_addr != LLDB_INVALID_ADDRESS) { 116 m_loaded_modules[executable] = load_addr; 117 return load_addr; 118 } 119 120 return LLDB_INVALID_ADDRESS; 121 } 122 123 void DynamicLoaderWindowsDYLD::DidAttach() { 124 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); 125 LLDB_LOGF(log, "DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); 126 127 ModuleSP executable = GetTargetExecutable(); 128 129 if (!executable.get()) 130 return; 131 132 // Try to fetch the load address of the file from the process, since there 133 // could be randomization of the load address. 134 lldb::addr_t load_addr = GetLoadAddress(executable); 135 if (load_addr == LLDB_INVALID_ADDRESS) 136 return; 137 138 // Request the process base address. 139 lldb::addr_t image_base = m_process->GetImageInfoAddress(); 140 if (image_base == load_addr) 141 return; 142 143 // Rebase the process's modules if there is a mismatch. 144 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); 145 146 ModuleList module_list; 147 module_list.Append(executable); 148 m_process->GetTarget().ModulesDidLoad(module_list); 149 auto error = m_process->LoadModules(); 150 LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); 151 } 152 153 void DynamicLoaderWindowsDYLD::DidLaunch() { 154 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); 155 LLDB_LOGF(log, "DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); 156 157 ModuleSP executable = GetTargetExecutable(); 158 if (!executable.get()) 159 return; 160 161 lldb::addr_t load_addr = GetLoadAddress(executable); 162 if (load_addr != LLDB_INVALID_ADDRESS) { 163 // Update the loaded sections so that the breakpoints can be resolved. 164 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); 165 166 ModuleList module_list; 167 module_list.Append(executable); 168 m_process->GetTarget().ModulesDidLoad(module_list); 169 auto error = m_process->LoadModules(); 170 LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); 171 } 172 } 173 174 Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); } 175 176 ConstString DynamicLoaderWindowsDYLD::GetPluginName() { 177 return GetPluginNameStatic(); 178 } 179 180 uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } 181 182 ThreadPlanSP 183 DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, 184 bool stop) { 185 auto arch = m_process->GetTarget().GetArchitecture(); 186 if (arch.GetMachine() != llvm::Triple::x86) { 187 return ThreadPlanSP(); 188 } 189 190 uint64_t pc = thread.GetRegisterContext()->GetPC(); 191 // Max size of an instruction in x86 is 15 bytes. 192 AddressRange range(pc, 2 * 15); 193 194 ExecutionContext exe_ctx(m_process->GetTarget()); 195 DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 196 arch, nullptr, nullptr, exe_ctx, range, true); 197 if (!disassembler_sp) { 198 return ThreadPlanSP(); 199 } 200 201 InstructionList *insn_list = &disassembler_sp->GetInstructionList(); 202 if (insn_list == nullptr) { 203 return ThreadPlanSP(); 204 } 205 206 // First instruction in a x86 Windows trampoline is going to be an indirect 207 // jump through the IAT and the next one will be a nop (usually there for 208 // alignment purposes). e.g.: 209 // 0x70ff4cfc <+956>: jmpl *0x7100c2a8 210 // 0x70ff4d02 <+962>: nop 211 212 auto first_insn = insn_list->GetInstructionAtIndex(0); 213 auto second_insn = insn_list->GetInstructionAtIndex(1); 214 215 if (first_insn == nullptr || second_insn == nullptr || 216 strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 || 217 strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) { 218 return ThreadPlanSP(); 219 } 220 221 assert(first_insn->DoesBranch() && !second_insn->DoesBranch()); 222 223 return ThreadPlanSP(new ThreadPlanStepInstruction( 224 thread, false, false, eVoteNoOpinion, eVoteNoOpinion)); 225 } 226