1 //===-- DynamicLoaderWindowsDYLD.cpp --------------------------------*- C++
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
8 //===----------------------------------------------------------------------===//
10 #include "DynamicLoaderWindowsDYLD.h"
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"
22 #include "llvm/ADT/Triple.h"
25 using namespace lldb_private;
27 DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
28 : DynamicLoader(process) {}
30 DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {}
32 void DynamicLoaderWindowsDYLD::Initialize() {
33 PluginManager::RegisterPlugin(GetPluginNameStatic(),
34 GetPluginDescriptionStatic(), CreateInstance);
37 void DynamicLoaderWindowsDYLD::Terminate() {}
39 ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() {
40 static ConstString g_plugin_name("windows-dyld");
44 const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() {
45 return "Dynamic loader plug-in that watches for shared library "
46 "loads/unloads in Windows processes.";
49 DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process,
51 bool should_create = force;
53 const llvm::Triple &triple_ref =
54 process->GetTarget().GetArchitecture().GetTriple();
55 if (triple_ref.getOS() == llvm::Triple::Win32)
60 return new DynamicLoaderWindowsDYLD(process);
65 void DynamicLoaderWindowsDYLD::OnLoadModule(lldb::ModuleSP module_sp,
66 const ModuleSpec module_spec,
67 lldb::addr_t module_addr) {
69 // Resolve the module unless we already have one.
72 module_sp = m_process->GetTarget().GetOrCreateModule(module_spec,
73 true /* notify */, &error);
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);
85 void DynamicLoaderWindowsDYLD::OnUnloadModule(lldb::addr_t module_addr) {
86 Address resolved_addr;
87 if (!m_process->GetTarget().ResolveLoadAddress(module_addr, resolved_addr))
90 ModuleSP module_sp = resolved_addr.GetModule();
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);
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)
106 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
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;
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;
120 return LLDB_INVALID_ADDRESS;
123 void DynamicLoaderWindowsDYLD::DidAttach() {
124 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
126 log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__);
128 ModuleSP executable = GetTargetExecutable();
130 if (!executable.get())
133 // Try to fetch the load address of the file from the process, since there
134 // could be randomization of the load address.
135 lldb::addr_t load_addr = GetLoadAddress(executable);
136 if (load_addr == LLDB_INVALID_ADDRESS)
139 // Request the process base address.
140 lldb::addr_t image_base = m_process->GetImageInfoAddress();
141 if (image_base == load_addr)
144 // Rebase the process's modules if there is a mismatch.
145 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false);
147 ModuleList module_list;
148 module_list.Append(executable);
149 m_process->GetTarget().ModulesDidLoad(module_list);
150 m_process->LoadModules();
153 void DynamicLoaderWindowsDYLD::DidLaunch() {
154 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
156 log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__);
158 ModuleSP executable = GetTargetExecutable();
159 if (!executable.get())
162 lldb::addr_t load_addr = GetLoadAddress(executable);
163 if (load_addr != LLDB_INVALID_ADDRESS) {
164 // Update the loaded sections so that the breakpoints can be resolved.
165 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false);
167 ModuleList module_list;
168 module_list.Append(executable);
169 m_process->GetTarget().ModulesDidLoad(module_list);
170 m_process->LoadModules();
174 Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); }
176 ConstString DynamicLoaderWindowsDYLD::GetPluginName() {
177 return GetPluginNameStatic();
180 uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; }
183 DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread,
185 auto arch = m_process->GetTarget().GetArchitecture();
186 if (arch.GetMachine() != llvm::Triple::x86) {
187 return ThreadPlanSP();
190 uint64_t pc = thread.GetRegisterContext()->GetPC();
191 // Max size of an instruction in x86 is 15 bytes.
192 AddressRange range(pc, 2 * 15);
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();
201 InstructionList *insn_list = &disassembler_sp->GetInstructionList();
202 if (insn_list == nullptr) {
203 return ThreadPlanSP();
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
212 auto first_insn = insn_list->GetInstructionAtIndex(0);
213 auto second_insn = insn_list->GetInstructionAtIndex(1);
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();
221 assert(first_insn->DoesBranch() && !second_insn->DoesBranch());
223 return ThreadPlanSP(new ThreadPlanStepInstruction(
224 thread, false, false, eVoteNoOpinion, eVoteNoOpinion));