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(const ModuleSpec &module_spec, 66 lldb::addr_t module_addr) { 67 // Confusingly, there is no Target::AddSharedModule. Instead, calling 68 // GetSharedModule() with a new module will add it to the module list and 69 // return a corresponding ModuleSP. 70 Status error; 71 ModuleSP module_sp = 72 m_process->GetTarget().GetSharedModule(module_spec, &error); 73 if (error.Fail()) 74 return; 75 76 m_loaded_modules[module_sp] = module_addr; 77 UpdateLoadedSectionsCommon(module_sp, module_addr, false); 78 } 79 80 void DynamicLoaderWindowsDYLD::OnUnloadModule(lldb::addr_t module_addr) { 81 Address resolved_addr; 82 if (!m_process->GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) 83 return; 84 85 ModuleSP module_sp = resolved_addr.GetModule(); 86 if (module_sp) { 87 m_loaded_modules.erase(module_sp); 88 UnloadSectionsCommon(module_sp); 89 } 90 } 91 92 lldb::addr_t DynamicLoaderWindowsDYLD::GetLoadAddress(ModuleSP executable) { 93 // First, see if the load address is already cached. 94 auto it = m_loaded_modules.find(executable); 95 if (it != m_loaded_modules.end() && it->second != LLDB_INVALID_ADDRESS) 96 return it->second; 97 98 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 99 100 // Second, try to get it through the process plugins. For a remote process, 101 // the remote platform will be responsible for providing it. 102 FileSpec file_spec(executable->GetPlatformFileSpec()); 103 bool is_loaded = false; 104 Status status = 105 m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); 106 // Servers other than lldb server could respond with a bogus address. 107 if (status.Success() && is_loaded && load_addr != LLDB_INVALID_ADDRESS) { 108 m_loaded_modules[executable] = load_addr; 109 return load_addr; 110 } 111 112 return LLDB_INVALID_ADDRESS; 113 } 114 115 void DynamicLoaderWindowsDYLD::DidAttach() { 116 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); 117 if (log) 118 log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); 119 120 ModuleSP executable = GetTargetExecutable(); 121 122 if (!executable.get()) 123 return; 124 125 // Try to fetch the load address of the file from the process, since there 126 // could be randomization of the load address. 127 lldb::addr_t load_addr = GetLoadAddress(executable); 128 if (load_addr == LLDB_INVALID_ADDRESS) 129 return; 130 131 // Request the process base address. 132 lldb::addr_t image_base = m_process->GetImageInfoAddress(); 133 if (image_base == load_addr) 134 return; 135 136 // Rebase the process's modules if there is a mismatch. 137 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); 138 139 ModuleList module_list; 140 module_list.Append(executable); 141 m_process->GetTarget().ModulesDidLoad(module_list); 142 m_process->LoadModules(); 143 } 144 145 void DynamicLoaderWindowsDYLD::DidLaunch() { 146 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); 147 if (log) 148 log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); 149 150 ModuleSP executable = GetTargetExecutable(); 151 if (!executable.get()) 152 return; 153 154 lldb::addr_t load_addr = GetLoadAddress(executable); 155 if (load_addr != LLDB_INVALID_ADDRESS) { 156 // Update the loaded sections so that the breakpoints can be resolved. 157 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); 158 159 ModuleList module_list; 160 module_list.Append(executable); 161 m_process->GetTarget().ModulesDidLoad(module_list); 162 m_process->LoadModules(); 163 } 164 } 165 166 Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); } 167 168 ConstString DynamicLoaderWindowsDYLD::GetPluginName() { 169 return GetPluginNameStatic(); 170 } 171 172 uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } 173 174 ThreadPlanSP 175 DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, 176 bool stop) { 177 auto arch = m_process->GetTarget().GetArchitecture(); 178 if (arch.GetMachine() != llvm::Triple::x86) { 179 return ThreadPlanSP(); 180 } 181 182 uint64_t pc = thread.GetRegisterContext()->GetPC(); 183 // Max size of an instruction in x86 is 15 bytes. 184 AddressRange range(pc, 2 * 15); 185 186 ExecutionContext exe_ctx(m_process->GetTarget()); 187 DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 188 arch, nullptr, nullptr, exe_ctx, range, true); 189 if (!disassembler_sp) { 190 return ThreadPlanSP(); 191 } 192 193 InstructionList *insn_list = &disassembler_sp->GetInstructionList(); 194 if (insn_list == nullptr) { 195 return ThreadPlanSP(); 196 } 197 198 // First instruction in a x86 Windows trampoline is going to be an indirect 199 // jump through the IAT and the next one will be a nop (usually there for 200 // alignment purposes). e.g.: 201 // 0x70ff4cfc <+956>: jmpl *0x7100c2a8 202 // 0x70ff4d02 <+962>: nop 203 204 auto first_insn = insn_list->GetInstructionAtIndex(0); 205 auto second_insn = insn_list->GetInstructionAtIndex(1); 206 207 if (first_insn == nullptr || second_insn == nullptr || 208 strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 || 209 strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) { 210 return ThreadPlanSP(); 211 } 212 213 assert(first_insn->DoesBranch() && !second_insn->DoesBranch()); 214 215 return ThreadPlanSP(new ThreadPlanStepInstruction( 216 thread, false, false, eVoteNoOpinion, eVoteNoOpinion)); 217 } 218