LLDB  mainline
DynamicLoaderWindowsDYLD.cpp
Go to the documentation of this file.
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 
11 
12 #include "lldb/Core/Module.h"
15 #include "lldb/Target/Platform.h"
16 #include "lldb/Target/Process.h"
18 #include "lldb/Target/Target.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 
31 
35 }
36 
38 
40  static ConstString g_plugin_name("windows-dyld");
41  return g_plugin_name;
42 }
43 
45  return "Dynamic loader plug-in that watches for shared library "
46  "loads/unloads in Windows processes.";
47 }
48 
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 
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 
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 
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 
125  if (log)
126  log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__);
127 
128  ModuleSP executable = GetTargetExecutable();
129 
130  if (!executable.get())
131  return;
132 
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)
137  return;
138 
139  // Request the process base address.
141  if (image_base == load_addr)
142  return;
143 
144  // Rebase the process's modules if there is a mismatch.
145  UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false);
146 
147  ModuleList module_list;
148  module_list.Append(executable);
149  m_process->GetTarget().ModulesDidLoad(module_list);
151 }
152 
155  if (log)
156  log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__);
157 
158  ModuleSP executable = GetTargetExecutable();
159  if (!executable.get())
160  return;
161 
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);
166 
167  ModuleList module_list;
168  module_list.Append(executable);
169  m_process->GetTarget().ModulesDidLoad(module_list);
171  }
172 }
173 
175 
177  return GetPluginNameStatic();
178 }
179 
181 
182 ThreadPlanSP
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 
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 }
void DidAttach() override
Called after attaching a process.
virtual Status GetFileLoadAddress(const FileSpec &file, bool &is_loaded, lldb::addr_t &load_addr)
Try to find the load address of a file.
Definition: Process.h:2313
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const ArchSpec & GetArchitecture() const
Definition: Target.h:941
static DynamicLoader * CreateInstance(Process *process, bool force)
static bool RegisterPlugin(ConstString name, const char *description, ABICreateInstance create_callback)
void OnUnloadModule(lldb::addr_t module_addr)
A file utility class.
Definition: FileSpec.h:55
lldb::addr_t GetLoadAddress(lldb::ModuleSP executable)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
void OnLoadModule(lldb::ModuleSP module_sp, const ModuleSpec module_spec, lldb::addr_t module_addr)
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
Status CanLoadImage() override
Ask if it is ok to try and load or unload an shared library (image).
A collection class for Module objects.
Definition: ModuleList.h:91
Process * m_process
The process that this dynamic loader plug-in is tracking.
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &disasm_range, bool prefer_file_cache)
lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec, bool notify, Status *error_ptr=nullptr)
Find a binary on the system and return its Module, or return an existing Module that is already in th...
Definition: Target.cpp:1999
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ModuleSP GetTargetExecutable()
Checks to see if the target module has changed, updates the target accordingly and returns the target...
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
bool Success() const
Test for success condition.
Definition: Status.cpp:287
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override
Provides a plan to step through the dynamic loader trampoline for the current state of thread...
virtual size_t LoadModules()
Sometimes processes know how to retrieve and load shared libraries.
Definition: Process.h:684
A section + offset based address class.
Definition: Address.h:80
void ModulesDidLoad(ModuleList &module_list)
Definition: Target.cpp:1651
A plug-in interface definition class for dynamic loaders.
Definition: DynamicLoader.h:64
#define LIBLLDB_LOG_DYNAMIC_LOADER
Definition: Logging.h:17
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1194
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition: Address.cpp:264
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
void UnloadSectionsCommon(const lldb::ModuleSP module)
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:61
Definition: SBAddress.h:15
void ModulesDidUnload(ModuleList &module_list, bool delete_locations)
Definition: Target.cpp:1686
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:2746
void UpdateLoadedSectionsCommon(lldb::ModuleSP module, lldb::addr_t base_addr, bool base_addr_is_offset)
virtual lldb::addr_t GetImageInfoAddress()
Get the image information address for the current process.
Definition: Process.cpp:1539
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
A section + offset based address range class.
Definition: AddressRange.h:32
void DidLaunch() override
Called after launching a process.
An error handling class.
Definition: Status.h:44
virtual void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, lldb::addr_t base_addr, bool base_addr_is_offset)
Updates the load address of every allocatable section in module.